blob: 720b1a4790b5794f044d026257483dd3c1926a44 [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.xpand2.ast.AbstractDefinition;
import org.eclipse.internal.xpand2.ast.Template;
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.XpandEvaluationRequest;
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.Type;
public class TemplateGroup extends AbstractGroup {
/**
* The template group dialog settings.
*/
protected static final String CODE_GEN_SECTION = Activator.getPlugin().getSymbolicName() + ".CODE_GEN_SECTION"; //$NON-NLS-1$
protected static final String STORE_TEMPLATE_FILE = "TEMPLATE_FILE$"; //$NON-NLS-1$
protected static final String STORE_SELECTED_DEFINITION = "SELECTED_DEFINITION"; //$NON-NLS-1$
/**
* The template file field.
*/
protected StringButtonField templateFileField;
/**
* The definition field.
*/
protected ComboField definitionField;
/**
* The definition name field.
*/
protected StringField definitionNameField;
/**
* The selected model object.
*/
protected EObject modelObject;
/**
* The {@link TypeSystem type system} to be used.
*/
protected TypeSystem typeSystem;
/**
* Defined definitions in the template file.
*/
private List<AbstractDefinition> definitions;
public TemplateGroup(String groupName, EObject modelObject, TypeSystem typeSystem) {
this(groupName, modelObject, typeSystem, null);
}
public TemplateGroup(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));
// Template file field
templateFileField = new StringButtonField(new IButtonAdapter() {
@Override
public void changeControlPressed(IField field) {
ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(parent.getShell(), new WorkbenchLabelProvider(),
new WorkbenchContentProvider());
dialog.setTitle(Messages.label_templateSelection);
dialog.setMessage(Messages.msg_chooseTemplate);
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.TEMPLATE_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.TEMPLATE_EXTENSION.equals(selectedFile.getFileExtension())) {
return Status.OK_STATUS;
}
}
return new Status(IStatus.ERROR, pluginId, IStatus.ERROR, Messages.msg_chooseTemplateError, null);
}
});
if (dialog.open() == IDialogConstants.OK_ID) {
IFile file = (IFile) dialog.getFirstResult();
if (file != null) {
templateFileField.setText(file.getFullPath().makeRelative().toString());
updateDefinitionFieldItems(file);
}
}
}
});
templateFileField.setButtonLabel(Messages.label_browse);
templateFileField.setLabelText(Messages.label_templateFile);
templateFileField.fillIntoGrid(parent, numColumns);
templateFileField.addFieldListener(new IFieldListener() {
@Override
public void dialogFieldChanged(IField field) {
updateDefinitionFieldItems(getFile(templateFileField.getText()));
updateDefinitionNameField();
notifyGroupChanged(templateFileField);
}
});
// Define block field
definitionField = new ComboField(true);
definitionField.setLabelText(Messages.label_definition);
definitionField.fillIntoGrid(parent, numColumns);
definitionField.addFieldListener(new IFieldListener() {
@Override
public void dialogFieldChanged(IField field) {
updateDefinitionNameField();
notifyGroupChanged(templateFileField);
}
});
// Definition name field
definitionNameField = new StringField();
definitionNameField.setLabelText(Messages.label_definitionName);
definitionNameField.setEditable(false);
definitionNameField.fillIntoGrid(parent, numColumns);
}
/**
* Updates items of define block field after loading selected template file.
*/
public void updateDefinitionFieldItems(IFile templateFile) {
Template template = loadTemplate(templateFile);
if (template != null) {
definitions = Arrays.asList(template.getAllDefinitions());
definitionField.setItems(createDefinitionFieldItems(definitions));
return;
}
definitionField.setItems(new String[0]);
}
/**
* Creates define block items.
*/
protected String[] createDefinitionFieldItems(List<AbstractDefinition> definitions) {
List<String> result = new ArrayList<String>();
Type type = typeSystem.getType(modelObject);
if (type != null) {
for (AbstractDefinition definition : definitions) {
// TODO Replace filtering based on target type names by one that takes inheritance hierarchy into
// account, just as org.eclipse.xpand2.XpandExecutionContextImpl.findDefinition(XpandDefinition[],
// String, Type, Type[], XpandExecutionContext) does; provide a new helper method similar to
// org.eclipse.sphinx.xtendxpand.util.XtendXpandUtil.getApplicableFeatures(List<? extends Callable>,
// Class<?>, String, List<? extends Type>) to XtendXpandUtil for that purpose
if (type.getName().equals(definition.getTargetType()) || getSimpleTypeName(type).equals(definition.getTargetType())) {
result.add(definition.getName());
}
}
}
// TODO Create an empty combo item if result is empty
return result.toArray(new String[result.size()]);
}
/**
* Gets the simple name of the given <code>type</type>.
*/
protected String getSimpleTypeName(Type type) {
String typeName = type.getName();
int idx = typeName.lastIndexOf(IXtendXpandConstants.NS_DELIMITER);
return idx != -1 && typeName.length() >= idx + IXtendXpandConstants.NS_DELIMITER.length() ? typeName.substring(idx
+ IXtendXpandConstants.NS_DELIMITER.length()) : typeName;
}
public String getDefinitionName() {
String selectedDefinitionName = getSelectedDefinitionFieldItem();
if (selectedDefinitionName != null) {
return XtendXpandUtil.getQualifiedName(getFile(getTemplateFileField().getText()), selectedDefinitionName);
}
return ""; //$NON-NLS-1$
}
protected void updateDefinitionNameField() {
IFile templateFile = getFile(templateFileField.getText());
if (templateFile != null) {
definitionNameField.setText(getDefinitionName());
} else {
definitionNameField.setText("..."); //$NON-NLS-1$
}
}
/**
* Loads an Xpand resource.
*/
protected Template loadTemplate(final IFile templateFile) {
if (templateFile != null && templateFile.exists() && IXtendXpandConstants.TEMPLATE_EXTENSION.equals(templateFile.getFileExtension())) {
final IXtendXpandProject project = org.eclipse.xtend.shared.ui.Activator.getExtXptModelManager().findProject(templateFile);
if (project != null) {
final IXtendXpandResource resource = project.findXtendXpandResource(templateFile);
if (resource != null) {
return (Template) resource.getExtXptResource();
}
}
}
return null;
}
@Override
public boolean isGroupComplete() {
IFile templateFile = getFile(getTemplateFileField().getText());
if (templateFile != null) {
return templateFile.exists() && getDefinitionField().getSelectionIndex() != -1;
}
return false;
}
/**
* Gets the file located at the given full path or returns null.
*/
public 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 StringButtonField getTemplateFileField() {
return templateFileField;
}
public ComboField getDefinitionField() {
return definitionField;
}
public String getSelectedDefinitionFieldItem() {
if (definitionField != null && !definitionField.getComboControl().isDisposed()) {
String[] items = definitionField.getItems();
int selectionIndex = definitionField.getSelectionIndex();
if (items.length > 0 && selectionIndex != -1) {
return items[selectionIndex];
}
}
return null;
}
public StringField getDefinitionNameField() {
return definitionNameField;
}
public List<AbstractDefinition> getDefinitions() {
return definitions;
}
public Collection<XpandEvaluationRequest> getXpandEvaluationRequests() {
List<XpandEvaluationRequest> requests = new ArrayList<XpandEvaluationRequest>();
if (modelObject != null) {
String definitionName = getDefinitionName();
if (definitionName != null && definitionName.length() > 0) {
requests.add(new XpandEvaluationRequest(definitionName, 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 templateFile = getTemplateFileFromDialogSettings();
if (templateFile != null) {
templateFileField.setText(templateFile);
updateDefinitionFieldItems(getFile(templateFile));
String definition = getDefinitionNameFromDialogSettings();
if (definition != null) {
definitionField.selectItem(definition);
}
}
}
public String getTemplateFileFromDialogSettings() {
String result = null;
String templateFileDialogSettingsKey = getTemplateFileDialogSettingsKey(modelObject);
IDialogSettings templateFileSection = getTemplateFileSection();
if (templateFileSection != null) {
String templateFilePath = templateFileSection.get(templateFileDialogSettingsKey);
if (templateFilePath != null) {
IFile templateFile = getFile(templateFilePath);
if (templateFile != null && templateFile.exists()) {
result = templateFilePath;
}
}
}
return result;
}
public String getDefinitionNameFromDialogSettings() {
String result = null;
IDialogSettings templateFileSection = getTemplateFileSection();
if (templateFileSection != null) {
result = templateFileSection.get(STORE_SELECTED_DEFINITION);
}
return result;
}
protected IDialogSettings getTemplateFileSection() {
IDialogSettings result = null;
String templateFileDialogSettingsKey = getTemplateFileDialogSettingsKey(modelObject);
IDialogSettings dialogSettings = getDialogSettings();
if (dialogSettings != null) {
IDialogSettings section = dialogSettings.getSection(CODE_GEN_SECTION);
if (section != null) {
result = section.getSection(templateFileDialogSettingsKey);
}
}
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();
if (settings != null) {
String key = getTemplateFileDialogSettingsKey(modelObject);
IDialogSettings topLevelSection = settings.getSection(CODE_GEN_SECTION);
if (topLevelSection == null) {
topLevelSection = settings.addNewSection(CODE_GEN_SECTION);
}
if (templateFileField.getText().trim().length() != 0) {
IDialogSettings templateFileSection = topLevelSection.getSection(key);
if (templateFileSection == null) {
templateFileSection = topLevelSection.addNewSection(key);
}
templateFileSection.put(key, templateFileField.getText());
String[] items = definitionField.getItems();
int selectionIndex = definitionField.getSelectionIndex();
if (items.length > 0 && selectionIndex != -1) {
templateFileSection.put(STORE_SELECTED_DEFINITION, items[selectionIndex]);
}
}
}
}
protected String getTemplateFileDialogSettingsKey(EObject object) {
Assert.isNotNull(object);
return TemplateGroup.STORE_TEMPLATE_FILE + EcoreResourceUtil.getURI(object).toString();
}
}