blob: 55e3c830e536d30c4e59cb37607eb0197464cfc2 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2011 See4sys, itemis and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* See4sys - Initial API and implementation
* itemis - [343844] Enable multiple Xtend MetaModels to be configured on BasicM2xAction, M2xConfigurationWizard, and Xtend/Xpand/CheckJob
* itemis - [357813] Risk of NullPointerException when transforming models using M2MConfigurationWizard
*
* </copyright>
*/
package org.eclipse.sphinx.xtendxpand.ui.groups;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.internal.xtend.xtend.ast.Extension;
import org.eclipse.internal.xtend.xtend.ast.ExtensionFile;
import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.sphinx.emf.mwe.IXtendXpandConstants;
import org.eclipse.sphinx.emf.util.EcorePlatformUtil;
import org.eclipse.sphinx.emf.util.EcoreResourceUtil;
import org.eclipse.sphinx.platform.ui.fields.ComboField;
import org.eclipse.sphinx.platform.ui.fields.IField;
import org.eclipse.sphinx.platform.ui.fields.IFieldListener;
import org.eclipse.sphinx.platform.ui.fields.StringButtonField;
import org.eclipse.sphinx.platform.ui.fields.StringField;
import org.eclipse.sphinx.platform.ui.fields.adapters.IButtonAdapter;
import org.eclipse.sphinx.platform.ui.groups.AbstractGroup;
import org.eclipse.sphinx.platform.util.ExtendedPlatform;
import org.eclipse.sphinx.xtendxpand.XtendEvaluationRequest;
import org.eclipse.sphinx.xtendxpand.ui.internal.Activator;
import org.eclipse.sphinx.xtendxpand.ui.internal.messages.Messages;
import org.eclipse.sphinx.xtendxpand.util.XtendXpandUtil;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceComparator;
import org.eclipse.xtend.expression.TypeSystem;
import org.eclipse.xtend.shared.ui.core.IXtendXpandProject;
import org.eclipse.xtend.shared.ui.core.IXtendXpandResource;
import org.eclipse.xtend.typesystem.Callable;
import org.eclipse.xtend.typesystem.Type;
public class ExtensionGroup extends AbstractGroup {
/**
* The extension group dialog settings.
*/
protected static final String M2M_TRANSFORM_SECTION = Activator.getPlugin().getSymbolicName() + ".M2M_TRANSFORM_SECTION"; //$NON-NLS-1$
protected static final String STORE_EXTENSION_FILE = "EXTENSION_FILE$"; //$NON-NLS-1$
protected static final String STORE_SELECTED_FUNCTION = "SELECTED_FUNCTION"; //$NON-NLS-1$
/**
* The Xtend file field.
*/
protected StringButtonField extensionFileField;
/**
* The function to be used in the relevant Xtend file.
*/
protected ComboField functionField;
/**
* The extension name field.
*/
protected StringField extensionNameField;
/**
* The selected model object.
*/
protected EObject modelObject;
/**
* The {@link TypeSystem type system} to be used.
*/
protected TypeSystem typeSystem;
/**
* Defined extensions in the relevant Xtend file.
*/
private List<Extension> extensions;
public ExtensionGroup(String groupName, EObject modelObject, TypeSystem typeSystem) {
this(groupName, modelObject, typeSystem, null);
}
public ExtensionGroup(String groupName, EObject modelObject, TypeSystem typeSystem, IDialogSettings dialogSettings) {
super(groupName, dialogSettings);
Assert.isNotNull(typeSystem);
this.modelObject = modelObject;
this.typeSystem = typeSystem;
}
@Override
protected void doCreateContent(final Composite parent, int numColumns) {
parent.setLayout(new GridLayout(numColumns, false));
// Extension file field
extensionFileField = new StringButtonField(new IButtonAdapter() {
@Override
public void changeControlPressed(IField field) {
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(parent.getShell(), new WorkbenchLabelProvider(),
new WorkbenchContentProvider());
dialog.setTitle(Messages.label_extensionSelection);
dialog.setMessage(Messages.msg_chooseExtension);
dialog.setInput(ResourcesPlugin.getWorkspace().getRoot());
IFile modelFile = EcorePlatformUtil.getFile(modelObject);
if (modelFile != null) {
dialog.setInitialSelection(modelFile.getProject());
}
dialog.setComparator(new ResourceComparator(ResourceComparator.NAME));
dialog.addFilter(new ViewerFilter() {
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if (element instanceof IFile) {
return IXtendXpandConstants.EXTENSION_EXTENSION.equals(((IFile) element).getFileExtension());
}
if (element instanceof IResource) {
return !ExtendedPlatform.isPlatformPrivateResource((IResource) element);
}
return true;
}
});
dialog.setValidator(new ISelectionStatusValidator() {
@Override
public IStatus validate(Object[] selection) {
int nSelected = selection.length;
String pluginId = Activator.getPlugin().getSymbolicName();
if (nSelected == 1 && selection[0] instanceof IFile) {
IFile selectedFile = (IFile) selection[0];
if (selectedFile.exists() && IXtendXpandConstants.EXTENSION_EXTENSION.equals(selectedFile.getFileExtension())) {
return Status.OK_STATUS;
}
}
return new Status(IStatus.ERROR, pluginId, IStatus.ERROR, Messages.msg_chooseExtensionError, null);
}
});
if (dialog.open() == IDialogConstants.OK_ID) {
IFile file = (IFile) dialog.getFirstResult();
if (file != null) {
extensionFileField.setText(file.getFullPath().makeRelative().toString());
updateFunctionFieldItems(file);
}
}
}
});
extensionFileField.setButtonLabel(Messages.label_browse);
extensionFileField.setLabelText(Messages.label_extensionFile);
extensionFileField.fillIntoGrid(parent, numColumns);
extensionFileField.addFieldListener(new IFieldListener() {
@Override
public void dialogFieldChanged(IField field) {
updateFunctionFieldItems(getFile(extensionFileField.getText()));
updateExtensionNameField();
notifyGroupChanged(extensionFileField);
}
});
// Function name field
functionField = new ComboField(true);
functionField.setLabelText(Messages.label_functionFieldName);
functionField.fillIntoGrid(parent, numColumns);
functionField.addFieldListener(new IFieldListener() {
@Override
public void dialogFieldChanged(IField field) {
updateExtensionNameField();
notifyGroupChanged(extensionFileField);
}
});
// Extension name field
extensionNameField = new StringField();
extensionNameField.setLabelText(Messages.label_extensionName);
extensionNameField.setEditable(false);
extensionNameField.fillIntoGrid(parent, numColumns);
}
/**
* Updates items of extensions combo field after loading selected Xtend file.
*/
public void updateFunctionFieldItems(IFile templateFile) {
ExtensionFile extensionFile = loadExtensionFile(templateFile);
if (extensionFile != null) {
extensions = extensionFile.getExtensions();
functionField.setItems(createFunctionFieldItems(extensions));
return;
}
functionField.setItems(new String[0]);
}
/**
* Creates extension items.
*/
protected String[] createFunctionFieldItems(List<Extension> extensions) {
List<String> result = new ArrayList<String>();
Type type = typeSystem.getType(modelObject);
if (type != null) {
for (Callable extension : XtendXpandUtil.getApplicableFeatures(extensions, Extension.class, null, Arrays.asList(type))) {
result.add(((Extension) extension).getName());
}
}
// TODO Create an empty combo item if result is empty
return result.toArray(new String[result.size()]);
}
public String getExtensionName() {
String selectedFunction = getSelectedFunctionFieldItem();
if (selectedFunction != null) {
return XtendXpandUtil.getQualifiedName(getFile(getExtensionFileField().getText()), selectedFunction);
}
return ""; //$NON-NLS-1$
}
protected void updateExtensionNameField() {
IFile templateFile = getFile(extensionFileField.getText());
if (templateFile != null) {
extensionNameField.setText(getExtensionName());
} else {
extensionNameField.setText("..."); //$NON-NLS-1$
}
}
/**
* Loads an Xtend resource.
*/
protected ExtensionFile loadExtensionFile(final IFile extensionFile) {
if (extensionFile != null && extensionFile.exists() && IXtendXpandConstants.EXTENSION_EXTENSION.equals(extensionFile.getFileExtension())) {
final IXtendXpandProject project = org.eclipse.xtend.shared.ui.Activator.getExtXptModelManager().findProject(extensionFile);
if (project != null) {
final IXtendXpandResource resource = project.findXtendXpandResource(extensionFile);
if (resource != null) {
return (ExtensionFile) resource.getExtXptResource();
}
}
}
return null;
}
@Override
public boolean isGroupComplete() {
IFile extensionFile = getFile(getExtensionFileField().getText());
if (extensionFile != null) {
return extensionFile.exists() && getFunctionField().getSelectionIndex() != -1;
}
return false;
}
/**
* Gets the file located at the given full path or returns null.
*/
protected IFile getFile(String fullPath) {
if (fullPath != null && fullPath.length() > 0) {
Path path = new Path(fullPath);
if (path.segmentCount() > 1) {
return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
}
}
return null;
}
public String getSelectedFunctionFieldItem() {
if (functionField != null && !functionField.getComboControl().isDisposed()) {
String[] items = functionField.getItems();
int selectionIndex = functionField.getSelectionIndex();
if (items.length > 0 && selectionIndex != -1) {
return items[selectionIndex];
}
}
return null;
}
public StringButtonField getExtensionFileField() {
return extensionFileField;
}
public ComboField getFunctionField() {
return functionField;
}
public List<Extension> getExtensions() {
return extensions;
}
public Collection<XtendEvaluationRequest> getXtendEvaluationRequests() {
List<XtendEvaluationRequest> requests = new ArrayList<XtendEvaluationRequest>();
if (modelObject != null) {
String extensionName = getExtensionName();
if (extensionName != null && extensionName.length() > 0) {
requests.add(new XtendEvaluationRequest(extensionName, modelObject));
}
}
return requests;
}
/**
* Loads the template path and the define block from the dialog settings. Must call
* {@link #setDialogSettings(IDialogSettings)} before calling this method.
*/
@Override
protected void loadGroupSettings() {
String extensionFile = getExtensionFileFromDialogSettings();
if (extensionFile != null) {
extensionFileField.setText(extensionFile);
updateFunctionFieldItems(getFile(extensionFile));
String functionName = getFunctionFromDialogSettings();
if (functionName != null) {
functionField.selectItem(functionName);
}
}
}
public String getExtensionFileFromDialogSettings() {
String result = null;
String key = getExtensionFileDialogSettingsKey(modelObject);
IDialogSettings extensionFileSection = getExtensionFileSection();
if (extensionFileSection != null) {
String extensionFilePath = extensionFileSection.get(key);
if (extensionFilePath != null) {
IFile extensionFile = getFile(extensionFilePath);
if (extensionFile != null && extensionFile.exists()) {
result = extensionFilePath;
}
}
}
return result;
}
public String getFunctionFromDialogSettings() {
String result = null;
IDialogSettings extensionFileSection = getExtensionFileSection();
if (extensionFileSection != null) {
result = extensionFileSection.get(STORE_SELECTED_FUNCTION);
}
return result;
}
protected IDialogSettings getExtensionFileSection() {
IDialogSettings result = null;
String key = getExtensionFileDialogSettingsKey(modelObject);
IDialogSettings section = getDialogSettings().getSection(M2M_TRANSFORM_SECTION);
if (section != null) {
result = section.getSection(key);
}
return result;
}
/**
* Saves, using the {@link DialogSettings} dialogSettings, the state of the different fields of this group.
*
* @param templatePathDialogSettingsKey
* @see #setDialogSettings(IDialogSettings)
*/
@Override
public void saveGroupSettings() {
IDialogSettings settings = getDialogSettings();
String extensionFileDialogSettingsKey = getExtensionFileDialogSettingsKey(modelObject);
if (settings != null) {
IDialogSettings topLevelSection = settings.getSection(M2M_TRANSFORM_SECTION);
if (topLevelSection == null) {
topLevelSection = settings.addNewSection(M2M_TRANSFORM_SECTION);
}
if (extensionFileField.getText().trim().length() != 0) {
IDialogSettings extensionFileSection = topLevelSection.getSection(extensionFileDialogSettingsKey);
if (extensionFileSection == null) {
extensionFileSection = topLevelSection.addNewSection(extensionFileDialogSettingsKey);
}
extensionFileSection.put(extensionFileDialogSettingsKey, extensionFileField.getText());
String[] items = functionField.getItems();
int selectionIndex = functionField.getSelectionIndex();
if (items.length > 0 && selectionIndex != -1) {
extensionFileSection.put(STORE_SELECTED_FUNCTION, items[selectionIndex]);
}
}
}
}
protected String getExtensionFileDialogSettingsKey(EObject object) {
Assert.isNotNull(object);
return ExtensionGroup.STORE_EXTENSION_FILE + EcoreResourceUtil.getURI(object).toString();
}
}