/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 *******************************************************************************/ /** * */ package org.ebayopensource.turmeric.eclipse.services.ui.wizards.pages; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.lang.StringUtils; import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger; import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants; import org.ebayopensource.turmeric.eclipse.exception.validation.ValidationInterruptedException; import org.ebayopensource.turmeric.eclipse.registry.ExtensionPointFactory; import org.ebayopensource.turmeric.eclipse.registry.exception.ClientProviderException; import org.ebayopensource.turmeric.eclipse.registry.intf.IClientRegistryProvider; import org.ebayopensource.turmeric.eclipse.registry.models.ClientAssetModel; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOAHelpProvider; import org.ebayopensource.turmeric.eclipse.repositorysystem.core.ISOARepositorySystem; import org.ebayopensource.turmeric.eclipse.repositorysystem.utils.TurmericServiceUtils; import org.ebayopensource.turmeric.eclipse.resources.model.AssetInfo; import org.ebayopensource.turmeric.eclipse.resources.model.IAssetInfo; import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil; import org.ebayopensource.turmeric.eclipse.resources.util.SOAConsumerUtil.EnvironmentItem; import org.ebayopensource.turmeric.eclipse.ui.SOABasePage; import org.ebayopensource.turmeric.eclipse.ui.components.AbstractSOAServiceListViewer; import org.ebayopensource.turmeric.eclipse.utils.collections.SetUtil; import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil; import org.ebayopensource.turmeric.eclipse.utils.ui.UIUtil; import org.ebayopensource.turmeric.eclipse.validator.core.ErrorMessage; import org.ebayopensource.turmeric.eclipse.validator.core.InputObject; import org.ebayopensource.turmeric.eclipse.validator.utils.common.NameValidator; import org.ebayopensource.turmeric.eclipse.validator.utils.common.RegExConstants; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Text; /** * The Class ConsumeNewServiceWizardPage. * * @author yayu */ public class ConsumeNewServiceWizardPage extends SOABasePage { private AbstractSOAServiceListViewer serviceList; private Set<AssetInfo> addedServices = new LinkedHashSet<AssetInfo>(); private Map<String, EnvironmentItem> addedEnvironments = new ConcurrentHashMap<String, EnvironmentItem>(); private Set<AssetInfo> existingServices = new LinkedHashSet<AssetInfo>(); private List<String> existingEnvironments = new ArrayList<String>(); private IProject project; private boolean isZeroConfig = false; private Text clientName; private Text consumerId; private String scppVersion; private Button retrieveConsumerIDBtn; private static final SOALogger logger = SOALogger.getLogger(); private static String SIMPLE_TITLE = "Set up configurations for services."; private static String ADV_TITLE = "Set up configurations for environments and services."; /** * Instantiates a new consume new service wizard page. * * @param project the project */ public ConsumeNewServiceWizardPage(final IProject project) { super("consumeNewServiceWizardPage"); setTitle("Set Up Consumer Configurations"); setDescription("Set up configurations for environments and services."); this.project = project; } public boolean isZeroConfig() { return this.isZeroConfig; } /** * {@inheritDoc} */ @Override public void createControl(Composite parent) { try { Composite composite = new Composite(parent, SWT.NONE); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); composite.setLayout(new GridLayout(4, false)); if (project != null) { final IFile propsFile = SOAConsumerUtil.getConsumerPropertiesFile(project); //the client name is default to be the project name String clientName = TurmericServiceUtils.isSOAImplProject(project) ? "" : this.project.getName(); String consumerId = ""; if (propsFile.exists() == true) { final Properties props = SOAConsumerUtil.loadConsumerProperties(project); clientName = StringUtils.trim(props.getProperty( SOAProjectConstants.PROPS_KEY_CLIENT_NAME, clientName)); consumerId = StringUtils.trim(props.getProperty( SOAProjectConstants.PROPS_KEY_CONSUMER_ID, "")); scppVersion = StringUtils.trim(props.getProperty( SOAProjectConstants.PROPS_KEY_SCPP_VERSION, "")); isZeroConfig = Boolean .valueOf(StringUtils.trim(props .getProperty( SOAProjectConstants.PROPS_SUPPORT_ZERO_CONFIG, Boolean.FALSE.toString()))); if (isZeroConfig) { setDescription(SIMPLE_TITLE); } else { setDescription(ADV_TITLE); } } else { logger.warning( "The underlying projects do not have service_consumer_project.properties file->", project.getName()); } final Text clientNameText = createClientNameText(composite, clientName); if (TurmericServiceUtils.isSOAImplProject(project) && TurmericServiceUtils.isSOAConsumerProject(project) == false && StringUtils.isEmpty(clientName)) { clientNameText.setText(StringUtils.substringBefore(project.getName(), SOAProjectConstants.IMPL_PROJECT_SUFFIX) + SOAProjectConstants.CLIENT_PROJECT_SUFFIX); } else { clientNameText.setText(clientName); } createConsumerIDText(composite, consumerId); createServiceList(composite); } setControl(composite); dialogChanged(); } catch (Exception e) { SOALogger.getLogger().error(e); UIUtil.showErrorDialog(e); } UIUtil.getHelpSystem().setHelp( parent, getHelpContextID()); } /** * Creates the client name text. * * @param parent the parent * @param defaultValue the default value * @return the text */ protected Text createClientNameText(Composite parent, String defaultValue) { this.clientName = super.createLabelTextField(parent, "Client &Name:", defaultValue, modifyListener, "the client name of the consumer"); this.clientName.setEditable(StringUtils.isBlank(defaultValue)); return clientName; } /** * Creates the consumer id text. * * @param parent the parent * @param defaultValue the default value * @return the text * @throws CoreException the core exception */ protected Text createConsumerIDText(Composite parent, String defaultValue) throws CoreException { this.consumerId = super.createLabelTextField(parent, "Consumer &ID:", defaultValue, modifyListener, false, false, "the consumer ID of the consumer"); boolean editable = false; //this field is only editable if //1) the underlying project is an impl project and has not consumed any services yet //2) the underlying project is consumer and created with scpp version. if (StringUtils.isBlank(defaultValue)) { //no consumer id yet if (StringUtils.isNotBlank(scppVersion)) { //a new project editable = true; } else if (TurmericServiceUtils.isSOAImplProject(project) && TurmericServiceUtils.isSOAConsumerProject(project) == false) { editable = true; } } this.consumerId.setEditable(editable); final IClientRegistryProvider clientRegProvider = ExtensionPointFactory.getSOAClientRegistryProvider(); if (clientRegProvider != null && editable == true) { this.retrieveConsumerIDBtn = new Button(parent, SWT.PUSH); this.retrieveConsumerIDBtn.setText("Retrie&ve"); setRetrieveConsumerIDEnabled(); retrieveConsumerIDBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (clientRegProvider != null) { try { ClientAssetModel clientModel = clientRegProvider.getClientAsset(getClientName()); if (clientModel != null) { String conID = StringUtils.isBlank(clientModel.getConsumerId()) ? "" : clientModel.getConsumerId(); consumerId.setText(conID); } } catch (ClientProviderException e1) { SOALogger.getLogger().error(e1); UIUtil.showErrorDialog(e1); } } } }); this.clientName.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { try { setRetrieveConsumerIDEnabled(); } catch (CoreException e1) { logger.warning(e1); } } }); } else { //AR plugin is not available super.createEmptyLabel(parent, 1); } return consumerId; } private void setRetrieveConsumerIDEnabled() throws CoreException { if (retrieveConsumerIDBtn != null) { retrieveConsumerIDBtn.setEnabled( ExtensionPointFactory.getSOAClientRegistryProvider() != null && StringUtils.isNotBlank(getClientName())); } } /** * Creates the service list. * * @param parent the parent * @return the composite * @throws Exception the exception */ protected Composite createServiceList(Composite parent) throws Exception { final Map<String, AssetInfo> dependencies = new ConcurrentHashMap<String, AssetInfo>(); for (final AssetInfo info : GlobalRepositorySystem.instanceOf() .getActiveRepositorySystem() .getAssetRegistry().getDependencies(project.getName())) { dependencies.put(info.getName(), info); } List<EnvironmentItem> items = new ArrayList<EnvironmentItem>(); if (isZeroConfig == false) { items = SOAConsumerUtil.getClientConfigStructure(project); for (EnvironmentItem item : items) { for (String serviceName : item.getServices()) { AssetInfo asset = dependencies.get(serviceName); if (asset == null) { logger.warning("Could not find service->", serviceName, " in the project dependency list->", project); } else { item.addServiceData(asset); existingServices.add(asset); } } existingEnvironments.add(item.getName()); } } this.serviceList = new AbstractSOAServiceListViewer(project, ISOAHelpProvider.WINDOW_SELECT_SERVICE) { @Override protected void serviceAdded(Collection<AssetInfo> services) { addedServices.addAll(services); dialogChanged(); } @Override protected void serviceRemoved(Object removedService) { addedServices.remove(removedService); dialogChanged(); } @Override protected void enviromentAdded(String environmentName, EnvironmentItem environmentForCopy) { if (environmentForCopy == null) { //this would cause NPE with HashTable or ConcurrentHashMap environmentForCopy = new EnvironmentItem(null); } addedEnvironments.put(environmentName, environmentForCopy); dialogChanged(); } @Override protected void environmentRemoved(EnvironmentItem environment) { addedEnvironments.remove(environment.getName()); dialogChanged(); } }; this.serviceList.setZeroConfig(isZeroConfig); if (items.isEmpty()) { //an impl project that does not have any environment yet EnvironmentItem envItem = new EnvironmentItem(SOAProjectConstants.DEFAULT_CLIENT_CONFIG_ENVIRONMENT); items.add(envItem); if (isZeroConfig == true) { for (AssetInfo asset : GlobalRepositorySystem.instanceOf().getActiveRepositorySystem() .getAssetRegistry().getDependencies(this.project.getName())) { if (IAssetInfo.TYPE_SERVICE_LIBRARY.equals(asset.getType())) { envItem.addServiceData(asset); existingServices.add(asset); } } } } final Composite container = this.serviceList.createControl(parent, items); return container; } /** * Key is the description of the AssetInfo instance. * * @return the added services info */ public Set<AssetInfo> getAddedServicesInfo() { return addedServices; } /** * Gets the services. * * @return the services */ public Set<AssetInfo> getServices() { final Set<AssetInfo> services = new LinkedHashSet<AssetInfo>(); if (this.serviceList != null) { final List<EnvironmentItem> items = this.serviceList.getServiceInfoList(); if (items.size() > 0) { for (Object service : items.get(0).getServiceData().values()) { if (service instanceof AssetInfo) services.add((AssetInfo)service); } } } return services; } /** * {@inheritDoc} */ @Override protected boolean dialogChanged() { super.dialogChanged(); boolean pageComplete = false; try { if (project == null || serviceList == null) return true; final List<EnvironmentItem> infoList = serviceList.getServiceInfoList(); if (TurmericServiceUtils.isSOAImplProject(project) == true) { final String clientName = getClientName(); if (StringUtils.isBlank(clientName) && (infoList.isEmpty() == false || infoList.get(0).getServices().isEmpty() == false)) { //client name is empty, but user has added environments and services updateStatus(this.clientName, "Client name must not be empty"); return false; } if (StringUtils.isNotBlank(clientName)) { if (clientName.equalsIgnoreCase(project.getName())) { updateStatus(this.clientName, "Client name should not be same as the implementation project name"); return false; } IProject clientProject = WorkspaceUtil.getProject(clientName); if(clientProject.exists() && TurmericServiceUtils.isSOAConsumerProject(clientProject)) { updateStatus(this.clientName, "Client name should not be same as the name of an existing consumer project->" + clientName); return false; } } try { final InputObject inputObject = new InputObject(clientName, RegExConstants.PROJECT_NAME_EXP, ErrorMessage.PROJECT_NAME_ERRORMSG + " The name [" + clientName + "] is not valid against the pattern \"" + RegExConstants.PROJECT_NAME_EXP + "\""); IStatus validationModel = NameValidator.getInstance().validate( inputObject); if (checkValidationResult(this.clientName, validationModel) == false) return false; final ISOARepositorySystem activeRepositorySystem = GlobalRepositorySystem .instanceOf().getActiveRepositorySystem(); validationModel = activeRepositorySystem.getServiceValidator() .validate(clientName); if (checkValidationResult(this.clientName, validationModel) == false) return false; } catch (ValidationInterruptedException e) { processException(e); } if (infoList.isEmpty() == false && infoList.get(0).getServices().isEmpty() == true) { updateStatus(serviceList.getServiceList().getTree(), "At least one service must be added"); return false; } if (TurmericServiceUtils.isSOAConsumerProject(project) == false) { //the underlying impl projects have not consumed any services yet if (infoList.isEmpty() == true) { updateStatus(serviceList.getServiceList().getTree(), "At least one environment must be added"); return false; } } pageComplete = true; } else if (TurmericServiceUtils.isSOAConsumerProject(project)) { //has consumer nature if (TurmericServiceUtils.isSOAImplProject(project) == false) { //not an impl project if (infoList.isEmpty() == true) { updateStatus(serviceList.getServiceList().getTree(), "At least one environment must be added"); return false; } if (infoList.get(0).getServices().isEmpty() == true) { updateStatus(serviceList.getServiceList().getTree(), "At least one service must be added"); return false; } } pageComplete = true; } } catch (CoreException e) { SOALogger.getLogger().error(e); UIUtil.showErrorDialog(e); this.setPageComplete(false); return false; } this.setPageComplete(pageComplete); return true; } /** * Gets the client name. * * @return the client name */ public String getClientName() { return this.clientName.getText(); } /** * Gets the consumer id. * * @return the consumer id */ public String getConsumerId() { return this.consumerId.getText(); } /** * Checks if is consumer id editable. * * @return true, if is consumer id editable */ public boolean isConsumerIdEditable() { return this.consumerId.getEditable(); } /* * Non destructive calculation */ /** * Gets the removed services. * * @return the removed services */ public Set<AssetInfo> getRemovedServices() { Set<AssetInfo> existingLibrariesSet = SetUtil.linkedSet(existingServices); // now this has the removed libraries, could be empty existingLibrariesSet.removeAll(getServices()); return existingLibrariesSet; } /** * Gets the added services. * * @return the added services */ public Set<AssetInfo> getAddedServices() { Set<AssetInfo> newLibrariesSet = getServices(); newLibrariesSet.removeAll(existingServices); // now this has the added new libraries, could be empty return newLibrariesSet; } /** * Gets the environments. * * @return the environments */ public Set<String> getEnvironments() { final Set<String> environments = new LinkedHashSet<String>(); if (this.serviceList != null) { for(EnvironmentItem item : this.serviceList.getServiceInfoList()) { environments.add(item.getName()); } } return environments; } /** * Gets the added environments. * * @return the added environments */ public Map<String, EnvironmentItem> getAddedEnvironments() { return addedEnvironments; } /** * Gets the removed environments. * * @return the removed environments */ public Set<String> getRemovedEnvironments() { Set<String> envs = SetUtil.hashSet(existingEnvironments); envs.removeAll(getEnvironments()); return envs; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.eclipse.ui.SOABasePage#getDefaultValue(org.eclipse.swt.widgets.Text) */ @Override public String getDefaultValue(Text text) { return ""; } /* (non-Javadoc) * @see org.ebayopensource.turmeric.eclipse.ui.SOABasePage#getHelpContextID() */ @Override public String getHelpContextID() { return GlobalRepositorySystem.instanceOf().getActiveRepositorySystem() .getHelpProvider().getHelpContextID( ISOAHelpProvider.PAGE_ADD_REMOVE_REQUIRED_SERVICES); } }