/*******************************************************************************
* 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.properties;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.ebayopensource.turmeric.eclipse.core.logging.SOALogger;
import org.ebayopensource.turmeric.eclipse.core.resources.constants.SOAProjectConstants.SupportedProjectType;
import org.ebayopensource.turmeric.eclipse.exception.resources.SOAResourceModifyFailedException;
import org.ebayopensource.turmeric.eclipse.exception.validation.ValidationInterruptedException;
import org.ebayopensource.turmeric.eclipse.repositorysystem.core.GlobalRepositorySystem;
import org.ebayopensource.turmeric.eclipse.repositorysystem.ui.utils.ActionUtil;
import org.ebayopensource.turmeric.eclipse.repositorysystem.utils.TurmericServiceUtils;
import org.ebayopensource.turmeric.eclipse.resources.model.ISOAProject;
import org.ebayopensource.turmeric.eclipse.resources.model.ISOAProject.SOAProjectSourceDirectory;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAConsumerMetadata;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAConsumerProject;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAImplProject;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAIntfMetadata;
import org.ebayopensource.turmeric.eclipse.resources.model.SOAIntfProject;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAIntfUtil;
import org.ebayopensource.turmeric.eclipse.resources.util.SOAServiceUtil;
import org.ebayopensource.turmeric.eclipse.services.ui.SOAMessages;
import org.ebayopensource.turmeric.eclipse.soatools.configtool.ConfigTool;
import org.ebayopensource.turmeric.eclipse.utils.plugin.ProgressUtil;
import org.ebayopensource.turmeric.eclipse.utils.plugin.WorkspaceUtil;
import org.ebayopensource.turmeric.eclipse.utils.ui.UIUtil;
import org.ebayopensource.turmeric.eclipse.validator.utils.common.ServiceVersionValidator;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchPropertyPage;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.osgi.framework.Version;
/**
* The Class SOAProjectPropertyPage.
*
* @author yayu
*/
public class SOAProjectPropertyPage extends PreferencePage implements
IWorkbenchPropertyPage {
private ISOAProject soaProject;
private static final SOALogger logger = SOALogger.getLogger();
private Combo serviceLayer;
private Text serviceVersion;
private Text implVersion;
private Text baseConsumerDir;
private String oldVersion;
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite)
*/
@Override
protected Control createContents(Composite parent) {
noDefaultAndApplyButton();
// create top panel
Composite result = new Composite(parent, SWT.NONE);
try {
GridLayout layout = new GridLayout();
layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
layout.marginWidth = 0;
layout.verticalSpacing = convertVerticalDLUsToPixels(10);
layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
result.setLayout(layout);
result.setLayoutData(new GridData(GridData.FILL_BOTH));
createGroups(result);
Dialog.applyDialogFont(result);
} catch (Exception e) {
logger.error(e);
UIUtil.showErrorDialog(e);
}
return result;
}
/**
* Create Groups.
* @param parent
* @throws Exception
*/
private void createGroups(Composite parent) throws Exception {
if (soaProject instanceof SOAIntfProject) {
createIntfGroups(parent);
} else if (soaProject instanceof SOAImplProject) {
createImplGroups(parent);
} else if (soaProject instanceof SOAConsumerProject) {
createConsumerGroups(parent);
}
}
private void createIntfGroups(Composite parent) throws Exception {
Group group = createServicePropertyGroup(parent);
boolean newSvc = SOAIntfUtil.getOldMetadataFile(soaProject.getProject(),
soaProject.getProjectName()).exists() == false;
final String svcName = newSvc ?
getIntfMetadata().getPublicServiceName() :
getIntfMetadata().getServiceName();
if (newSvc == true) {
addAdminName(group);
}
addServiceName(group, svcName);
addServiceVersion(group, true);
addServiceLayerCombo(group, true);
addServiceIntfClassName(group);
this.validateAll();
}
private void createConsumerGroups(Composite parent) {
Group group = createConsumerPropertyGroup(parent);
addClientName(group);
addConsumerId(group);
addBaseConsumerSrcDir(group);// consumer
}
private void createImplGroups(Composite parent) throws Exception {
Group serviceGroup = createServicePropertyGroup(parent);
final String adminName = getIntfMetadata().getServiceName();
final String svcName = getIntfMetadata().getPublicServiceName();
if (StringUtils.isNotBlank(adminName)) {
addAdminName(serviceGroup);
}
addServiceName(serviceGroup, svcName);
addServiceVersion(serviceGroup, false);
addServiceLayerCombo(serviceGroup, false);
addServiceIntfClassName(serviceGroup);
// create second group
Group group = createImplPropertyGroup(parent);
addImplVersion(group);
addServiceImplClassName(group);
if (this.soaProject.getProject()
.hasNature(GlobalRepositorySystem.instanceOf().getActiveRepositorySystem()
.getProjectNatureId(SupportedProjectType.CONSUMER))) {
//is a consumer project also
Group consumerGroup = createConsumerPropertyGroup(parent);
addClientName(consumerGroup);
addConsumerId(consumerGroup);
addBaseConsumerSrcDir(consumerGroup);
}
}
/**
* @param parent
* @return
*/
private Group createServicePropertyGroup(Composite parent) {
Group servicePropertyGroup = new Group(parent, SWT.NONE);
servicePropertyGroup.setLayout(new GridLayout(2, false));
servicePropertyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
true, false));
servicePropertyGroup.setText("Service Properties");
return servicePropertyGroup;
}
/**
* @param parent
* @return
*/
private Group createImplPropertyGroup(Composite parent) {
Group implPropertyGroup = new Group(parent, SWT.NONE);
implPropertyGroup.setLayout(new GridLayout(2, false));
implPropertyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
false));
implPropertyGroup.setText("Implementation Properties");
return implPropertyGroup;
}
private Group createConsumerPropertyGroup(Composite parent) {
Group consumerPropertyGroup = new Group(parent, SWT.NONE);
consumerPropertyGroup.setLayout(new GridLayout(2, false));
consumerPropertyGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
false));
consumerPropertyGroup.setText("Consumer Properties");
return consumerPropertyGroup;
}
/**
* {@inheritDoc}
* @see org.eclipse.jface.preference.PreferencePage#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createControl(Composite parent) {
super.createControl(parent);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IWorkbenchPropertyPage#getElement()
*/
@Override
public IAdaptable getElement() {
return null;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.preference.PreferencePage#performOk()
*/
@Override
public boolean performOk() {
try {
if (soaProject instanceof SOAIntfProject) {
final SOAIntfMetadata intfMetadata = ((SOAIntfProject) soaProject)
.getMetadata();
final String oldVersion = intfMetadata.getServiceVersion();
String oldServiceLayer = intfMetadata.getServiceLayer();
final String newVersion = serviceVersion.getText();
String newLayer = serviceLayer.getText();
if (StringUtils.equalsIgnoreCase(oldVersion, newVersion) == true
&& StringUtils.equalsIgnoreCase(oldServiceLayer,
newLayer) == true) {
return true;
}
logger.info("Modify service " + soaProject.getProjectName()
+ ": new version is " + newVersion + ". New layer is: "
+ newLayer);
intfMetadata.setServiceVersion(serviceVersion.getText());
intfMetadata.setServiceLayer(serviceLayer.getText());
final WorkspaceModifyOperation operation = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor)
throws CoreException, InvocationTargetException,
InterruptedException {
monitor.beginTask("Updating project->"
+ soaProject.getProjectName(),
ProgressUtil.PROGRESS_STEP * 10);
try {
if (StringUtils.equals(oldVersion,newVersion) == true) {
//only service layer changed
SOAIntfUtil.saveMetadataProps((SOAIntfProject) soaProject, monitor);
} else {
// change local metadata (wsdl, properties), sync AR version.
ActionUtil
.updateInterfaceProjectVersion(
(SOAIntfProject) soaProject,
oldVersion, newVersion, false, monitor);
}
} catch (Exception e) {
logger.error(e);
throw new SOAResourceModifyFailedException(
"Failed to modify project properties for project->"
+ soaProject.getProjectName(), e);
} finally {
monitor.done();
}
}
};
try {
new ProgressMonitorDialog(getControl().getShell()).run(false,
true, operation);
return true;
} catch (Exception e) {
logger.error(e);
UIUtil.showErrorDialog(e);
return false;
}
} else if (soaProject instanceof SOAImplProject) {
// skip the modification for impl
return true;
} else if (soaProject instanceof SOAConsumerProject) {
// we do not support changing properties for consumer
return true;
}else {
return false;
}
} catch (Exception e) {
logger.error(e);
UIUtil.showErrorDialog(
"Error Occurred While Saving Project Properties", e);
return false;
}
}
/**
*
* create a text and a label.
*
* @param composite
* @param label
* @param isEditable
* @param defaultValue
*/
private Text createLabeledText(Composite composite, String label,
boolean isEditable, String defaultValue) {
new Label(composite, SWT.LEFT).setText(label);
Text text = new Text(composite, SWT.BORDER);
text.setEditable(isEditable);
text.setText(StringUtils.defaultString(defaultValue));
text.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL
| GridData.FILL_HORIZONTAL));
return text;
}
private void addServiceIntfClassName(Composite group) {
createLabeledText(group, "Interface Class:", false, getIntfMetadata()
.getServiceInterface());
}
private void addServiceImplClassName(Group group) {
createLabeledText(group, "Impl Class:", false,
((SOAImplProject) getSoaProject()).getMetadata()
.getServiceImplClassName());
}
private void addImplVersion(Group group) {
String defaultValue = ((SOAImplProject) getSoaProject()).getMetadata()
.getImplVersion();
final Text text = createLabeledText(group, "Impl Version:", false,
defaultValue);
this.implVersion = text;
text.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
try {
validateAll();
} catch (ValidationInterruptedException e1) {
processException(e1);
}
}
});
}
private void addServiceVersion(Composite group, final boolean editable) {
oldVersion = getIntfMetadata().getServiceVersion();
this.serviceVersion = createLabeledText(group, "Service Version:",
editable, oldVersion);
this.serviceVersion.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
try {
validateAll();
} catch (ValidationInterruptedException e1) {
processException(e1);
}
}
});
}
private void addAdminName(Composite group) {
createLabeledText(group, "Admin Name:", false, getIntfMetadata()
.getServiceName());
}
private void addServiceName(Composite group, final String svcName) {
createLabeledText(group, "Service Name:", false, svcName);
}
private void addClientName(Composite comp) {
createLabeledText(comp, "Client Name:", false,
getConsumerMetadata().getClientName());
}
private void addConsumerId(Composite comp) {
final String conId = getConsumerMetadata().getConsumerId() != null
? getConsumerMetadata().getConsumerId() : "";
createLabeledText(comp, "Consumer ID:", false,
conId);
}
private boolean isValidLayer(final String svcLayer,
final List<String> requiredSvcLayers) {
for (final String requiredSvcLayer : requiredSvcLayers) {
if (SOAServiceUtil.validateServiceLayer(svcLayer, requiredSvcLayer) == false)
return false;
}
return true;
}
private void addServiceLayerCombo(Composite group, final boolean enabled)
throws Exception {
new Label(group, SWT.LEFT).setText("Service Layer:");
final List<String> layers = new ArrayList<String>();
final SOAIntfMetadata intfMetadata = getIntfMetadata();
final String implProjectName = intfMetadata
.getImlementationProjectName();
if (enabled == true && StringUtils.isNotBlank(implProjectName)) {
// this is an intf project, and we should only show the valid layers
final IProject project = WorkspaceUtil.getProject(implProjectName);
if (project != null && project.isAccessible()) {
final ISOAProject soaProject = GlobalRepositorySystem
.instanceOf().getActiveRepositorySystem()
.getAssetRegistry().getSOAProject(project);
if (soaProject instanceof SOAImplProject) {
final SOAImplProject implProject = (SOAImplProject) soaProject;
final List<String> requiredSvcLayers = new ArrayList<String>();
for (final SOAIntfMetadata metadata : implProject
.getRequiredServices().values()) {
requiredSvcLayers.add(metadata.getServiceLayer());
}
for (final String layer : ConfigTool
.getDefaultServiceLayersFromFile()) {
if (isValidLayer(layer, requiredSvcLayers))
// we only add those layers that are compatible with
// the impl's required services
layers.add(layer);
}
}
}
} else {
layers.addAll(ConfigTool.getDefaultServiceLayersFromFile());
}
if (layers.isEmpty() == true) {
layers.add(intfMetadata.getServiceLayer());
}
Combo combo = new Combo(group, SWT.READ_ONLY | SWT.BORDER);
this.serviceLayer = combo;
// Service Layer:
if (layers != null)
this.serviceLayer.setItems(layers.toArray(new String[0]));
if (layers.size() > 0) {
if (layers.contains(intfMetadata.getServiceLayer()))
serviceLayer.setText(intfMetadata.getServiceLayer());
else
serviceLayer.setText(layers.get(0));
}
// the service layer can only be changed if there are more than one
// layers available for selection
serviceLayer.setEnabled(enabled && layers.size() > 1
&& StringUtils.isNotBlank(serviceLayer.getText()));
}
private void addBaseConsumerSrcDir(Composite group) {
final List<SOAProjectSourceDirectory> srcDirs = soaProject
.getSourceDirectories();
Collections.sort(srcDirs);
baseConsumerDir = createLabeledText(group, "Consumer Src Dir:", false,
getConsumerMetadata().getBaseConsumerSrcDir());
}
private SOAIntfMetadata getIntfMetadata() {
if (soaProject instanceof SOAIntfProject) {
return ((SOAIntfProject) soaProject).getMetadata();
} else if (soaProject instanceof SOAImplProject) {
return ((SOAImplProject) soaProject).getMetadata()
.getIntfMetadata();
}
return null;
}
private SOAConsumerMetadata getConsumerMetadata() {
if (soaProject instanceof SOAImplProject) {
return ((SOAImplProject) soaProject).getMetadata();
} else if (soaProject instanceof SOAConsumerProject) {
return ((SOAConsumerProject) soaProject).getMetadata();
}
return null;
}
private void validateAll() throws ValidationInterruptedException {
boolean result = true;
if (soaProject instanceof SOAIntfProject) {
result = validateIntfProjectFields();
} else if (soaProject instanceof SOAImplProject) {
result = validateImplProjectFields();
} else if (soaProject instanceof SOAConsumerProject) {
result = validateConsumerProjectFields();
}
if (result == false) {
setValid(false);
return;
}
setValid(true);
setErrorMessage(null);
}
private boolean validateIntfProjectFields()
throws ValidationInterruptedException {
if (serviceVersion != null) {
final IStatus validationModel = ServiceVersionValidator
.getInstance().validate(serviceVersion.getText());
if (validationModel.isOK() == false) {
setErrorMessage(validationModel.getMessage());
return false;
}
if (soaProject instanceof SOAIntfProject) {
final SOAIntfProject intfProject = (SOAIntfProject) soaProject;
final Version newVer = new Version(serviceVersion.getText());
String curVersion = intfProject.getMetadata().getServiceVersion();
if (StringUtils.isEmpty(curVersion)) {
return true;
}
final Version existingVer = new Version(curVersion);
if (newVer.getMajor() != existingVer.getMajor()) {
setErrorMessage(SOAMessages.ERR_CHANGE_MAJOR_VERSION_NOT_ALLOWED);
return false;
}
IStatus status =
ServiceVersionValidator.getInstance().validate(newVer.toString());
if (status.isOK() == false) {
setErrorMessage(status.getMessage());
return false;
}
}
}
return true;
}
private boolean validateImplProjectFields()
throws ValidationInterruptedException {
if (implVersion != null) {
final IStatus validationModel = ServiceVersionValidator
.getInstance().validate(implVersion.getText());
if (validationModel.isOK() == false) {
setErrorMessage(validationModel.getMessage());
return false;
}
}
return true;
}
/**
* Validate consumer project fields.
*
* @return true, if successful
*/
public boolean validateConsumerProjectFields() {
if (StringUtils.isNotBlank(baseConsumerDir.getText())) {
setErrorMessage("Base comsumer source dir could be null");
return false;
}
return true;
}
/**
* {@inheritDoc}
* @see org.eclipse.ui.IWorkbenchPropertyPage#setElement(org.eclipse.core.runtime.IAdaptable)
*/
@Override
public void setElement(IAdaptable element) {
try {
if (element.getAdapter(IProject.class) instanceof IProject) {
IProject project = (IProject) element
.getAdapter(IProject.class);
if (TurmericServiceUtils.isSOAProject(project)) {
soaProject = GlobalRepositorySystem.instanceOf()
.getActiveRepositorySystem().getAssetRegistry()
.getSOAProject(project);
}
}
} catch (Exception e) {
logger.error(e);
}
}
/**
* Gets the soa project.
*
* @return the soa project
*/
public ISOAProject getSoaProject() {
return soaProject;
}
private void processException(Exception exception) {
if (exception != null) {
UIUtil.showErrorDialog(exception);
SOALogger.getLogger().error(exception);
}
}
}