blob: 3d049de607d1b308fa712bad20068f552b99d236 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 THALES GLOBAL SERVICES and Others
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.ecoretools.design.ui.wizard;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.emf.codegen.ecore.genmodel.provider.GenModelEditPlugin;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.util.EcoreValidator;
import org.eclipse.emf.ecoretools.design.service.EcoreToolsDesignPlugin;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.sirius.business.api.helper.SiriusUtil;
import org.eclipse.sirius.business.api.modelingproject.ModelingProject;
import org.eclipse.sirius.business.api.query.DViewQuery;
import org.eclipse.sirius.business.api.session.Session;
import org.eclipse.sirius.common.tools.api.util.ReflectionHelper;
import org.eclipse.sirius.common.tools.api.util.StringUtil;
import org.eclipse.sirius.common.ui.tools.api.util.EclipseUIUtil;
import org.eclipse.sirius.ext.base.Option;
import org.eclipse.sirius.ui.business.api.dialect.DialectUIManager;
import org.eclipse.sirius.ui.tools.api.wizards.page.ViewpointsSelectionWizardPage;
import org.eclipse.sirius.viewpoint.DRepresentation;
import org.eclipse.sirius.viewpoint.DView;
import org.eclipse.sirius.viewpoint.description.Viewpoint;
import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.part.ISetSelectionTarget;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
* Wizard to create an EMF project with the {@link ModelingProject} nature, an
* Ecore model and its associated genmodel and an aird file.
*
* @author mporhel
*/
public class EcoreModelerWizard extends BasicNewProjectResourceWizard {
/** The name of the Design viewpoint. */
private static final String DESIGN_VIEWPOINT_NAME = "Design"; //$NON-NLS-1$
private EcoreModelSpecPage modelPage;
private ViewpointsSelectionWizardPage viewpointsSelectionWizardPage;
private WizardNewProjectCreationPage wizardNewProjectCreationPage;
protected IWorkbench workbench;
protected IPath genModelProjectLocation;
protected IPath genModelContainerPath;
protected String initialProjectName;
protected IStructuredSelection selection;
private IProject createdProject;
/**
* Constructor.
*/
public EcoreModelerWizard() {
super();
}
@Override
public void init(IWorkbench workbench, IStructuredSelection selection) {
super.init(workbench, selection);
this.workbench = workbench;
this.selection = selection;
setDefaultPageImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(GenModelEditPlugin.INSTANCE.getImage("full/wizban/NewEmptyEMFProject")));
setWindowTitle(GenModelEditPlugin.INSTANCE.getString("_UI_NewEmptyProject_title"));
setWindowTitle("New Ecore Modeling Project"); //$NON-NLS-1$
setDefaultPageImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(EcoreToolsDesignPlugin.PLUGIN_ID, "icons/full/wizban/EcoreModelingProject_wizban.png"));
setNeedsProgressMonitor(true);
}
/**
* {@inheritDoc}
*/
@Override
public void addPages() {
wizardNewProjectCreationPage = new WizardNewProjectCreationPage(SiriusEditPlugin.getPlugin().getString("_UI_ModelingProjectWizard_label")) {
@Override
public void createControl(Composite parent) {
super.createControl(parent);
Composite control = (Composite) getControl();
GridLayout layout = new GridLayout();
control.setLayout(layout);
createWorkingSetGroup(control, new StructuredSelection(), new String[] { "org.eclipse.jdt.ui.JavaWorkingSetPage", //$NON-NLS-1$
"org.eclipse.pde.ui.pluginWorkingSet", "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$ //$NON-NLS-2$
Dialog.applyDialogFont(control);
}
@Override
protected boolean validatePage() {
if (super.validatePage()) {
IPath locationPath = getLocationPath();
genModelProjectLocation = Platform.getLocation().equals(locationPath) ? null : locationPath;
IPath projectPath = getProjectHandle().getFullPath();
genModelContainerPath = projectPath.append("src"); //$NON-NLS-1$
updateModelPagePackageName(getProjectName());
return true;
} else {
return false;
}
}
private void updateModelPagePackageName(String projectName) {
if (!StringUtil.isEmpty(projectName)) {
String packageName = getPackageName(projectName);
if (!StringUtil.isEmpty(packageName)) {
modelPage.setPackageNameSilently(packageName);
}
}
}
};
wizardNewProjectCreationPage.setInitialProjectName(initialProjectName);
wizardNewProjectCreationPage.setTitle("Create a new Ecore Modeling project"); //$NON-NLS-1$
wizardNewProjectCreationPage.setDescription("Enter a project name"); //$NON-NLS-1$
modelPage = new EcoreModelSpecPage("Ecore model parameters"); //$NON-NLS-1$
modelPage.setTitle("Model settings"); //$NON-NLS-1$
modelPage.setDescription("Define the model settings"); //$NON-NLS-1$
viewpointsSelectionWizardPage = new ViewpointsSelectionWizardPage(null, Lists.newArrayList(DESIGN_VIEWPOINT_NAME)) {
@Override
protected Collection<String> computeSemanticFileExtensions(Session session) {
Set<String> fileExtensions = new HashSet<String>();
fileExtensions.add("ecore");
return fileExtensions;
}
};
// Fix for VP-3711 to avoid a NPE on 3.8
ReflectionHelper.setFieldValueWithoutException(this, "newProjectCreationPage", wizardNewProjectCreationPage);
addPage(wizardNewProjectCreationPage);
addPage(modelPage);
addPage(viewpointsSelectionWizardPage);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.wizard.Wizard#performFinish()
*/
@Override
public boolean performFinish() {
boolean finished = true;
updatePerspective();
final EcoreModelingProjectCreationOperation ecoreModelingProjectCreationOperation = new EcoreModelingProjectCreationOperation(modelPage.getEPackage(), modelPage.getEcoreFileName(),
modelPage.getGenModelFileName(), modelPage.getRepresentationFileName(), new LinkedHashSet<Viewpoint>(viewpointsSelectionWizardPage.getViewpoints()), workbench, genModelContainerPath,
genModelProjectLocation, wizardNewProjectCreationPage.getSelectedWorkingSets());
try {
getContainer().run(true, false, ecoreModelingProjectCreationOperation);
} catch (InvocationTargetException e) {
IStatus status = new Status(IStatus.ERROR, EcoreToolsDesignPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e);
EcoreToolsDesignPlugin.INSTANCE.log(status);
finished = false;
} catch (InterruptedException e) {
IStatus status = new Status(IStatus.ERROR, EcoreToolsDesignPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e);
EcoreToolsDesignPlugin.INSTANCE.log(status);
finished = false;
}
try {
getContainer().run(false, false, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
try {
monitor.beginTask("Open the diagram metamodel", 2);
IFile ecoreModel = ecoreModelingProjectCreationOperation.getEcoreModel();
createdProject = ecoreModelingProjectCreationOperation.getNewProject();
if (ecoreModel != null && ecoreModel.exists()) {
selectAndReveal(ecoreModel);
} else {
selectAndReveal(ecoreModelingProjectCreationOperation.getNewProject());
}
monitor.worked(1);
// Open the entities diagram, of the root of the
// ecore
// file,
// that is automatically created (because the
// Entities
// diagram has
// the "initialization" to true).
// This can fail if the user deselects the "Design"
// viewpoint in the second page of the wizard.
openFirstRepresentation(ecoreModelingProjectCreationOperation.getNewProject(), new SubProgressMonitor(monitor, 1));
} finally {
monitor.done();
}
}
});
} catch (InvocationTargetException e) {
IStatus status = new Status(IStatus.ERROR, EcoreToolsDesignPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e);
EcoreToolsDesignPlugin.INSTANCE.log(status);
finished = false;
} catch (InterruptedException e) {
IStatus status = new Status(IStatus.ERROR, EcoreToolsDesignPlugin.PLUGIN_ID, IStatus.ERROR, e.getMessage(), e);
EcoreToolsDesignPlugin.INSTANCE.log(status);
finished = false;
}
return finished;
}
@Override
public IProject getNewProject() {
return createdProject;
}
/**
* Selects and reveals the newly added resource in all parts of the active
* workbench window's active page.
*
* @see ISetSelectionTarget
*/
protected void selectAndReveal(IResource newResource) {
BasicNewResourceWizard.selectAndReveal(newResource, workbench.getActiveWorkbenchWindow());
EclipseUIUtil.expand(newResource, workbench.getActiveWorkbenchWindow());
}
/**
* Open the first representation containing in the representation file of
* this Modeling project.
*
* @param project
* The modeling project containing the representations file.
* @param monitor
* a {@link IProgressMonitor} to show progression of first
* {@link DRepresentation} opening
*/
private void openFirstRepresentation(IProject project, IProgressMonitor monitor) {
Option<ModelingProject> opionalModelingProject = ModelingProject.asModelingProject(project);
if (opionalModelingProject.some()) {
Session session = opionalModelingProject.get().getSession();
if (session != null) {
if (!session.getSelectedViews().isEmpty()) {
Set<DRepresentation> representationsToOpen = Sets.newLinkedHashSet();
for (DView view : session.getSelectedViews()) {
for (DRepresentation dRepresentation : new DViewQuery(view).getLoadedRepresentations()) {
representationsToOpen.add(dRepresentation);
}
}
for (DRepresentation dRepresentation : representationsToOpen) {
DialectUIManager.INSTANCE.openEditor(session, dRepresentation, monitor);
}
}
}
}
}
public void setInitialProjectName(String value) {
initialProjectName = value;
}
private String getPackageName(String projectName) {
String packageName = projectName.substring(0, 1).toLowerCase() + projectName.substring(1);
int index = packageName.lastIndexOf('.');
if (index != -1) {
packageName = packageName.substring(index + 1);
}
return packageName;
}
private class EcoreModelSpecPage extends WizardPage {
private static final String NAMESPACE_GROUP_LABEL = "Namespace properties";//$NON-NLS-1$
private static final String NS_PREFIX_FIELD_LABEL = "Ns Prefix"; //$NON-NLS-1$
private static final String NS_URI_FIELD_LABEL = "Ns Uri"; //$NON-NLS-1$
private static final String USE_DEFAULT_LABEL = "Use default namespace parameters"; //$NON-NLS-1$
private static final String PACKAGE_FIELD_LABEL = "Main package name"; //$NON-NLS-1$
private static final String DEFAULT_URI_BASE = "http://www.example.org/"; //$NON-NLS-1$
private static final String DEFAULT_COMMON_FILE_NAME = "model"; //$NON-NLS-1$
// widgets
private Text packageNameField;
private Text nsPrefixField;
private Text nsUriField;
private Button useDefaultsButton;
private EPackage ePackage;
private boolean silentModificationEnabled = true;
private final ModifyListener nsModifyListener = new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (!(useDefaultsButton != null && useDefaultsButton.getSelection())) {
setPageComplete(validatePage());
}
}
};
public EcoreModelSpecPage(String name) {
super(name);
}
/**
* Allow an other page to set the package name until the user manualy
* modify it.
*
* @param packageName
* the package name to set.
*/
public void setPackageNameSilently(String packageName) {
if (packageNameField != null && silentModificationEnabled) {
packageNameField.setText(packageName);
}
}
/**
* {@inheritDoc}
*/
public void createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NULL);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
createModelGroup(composite);
createNamespaceGroup(composite, false);
setPageComplete(validatePage());
setControl(composite);
Dialog.applyDialogFont(composite);
}
private void createModelGroup(Composite parent) {
packageNameField = createLabelAndText(parent, PACKAGE_FIELD_LABEL, getPackageName());
packageNameField.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
if (packageNameField.isVisible()) {
silentModificationEnabled = false;
}
updateNamespaceValues();
setPageComplete(validatePage());
}
});
}
private void createNamespaceGroup(Composite composite, boolean custom) {
Group nsGroup = new Group(composite, SWT.NONE);
nsGroup.setFont(composite.getFont());
nsGroup.setText(NAMESPACE_GROUP_LABEL);
nsGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
nsGroup.setLayout(new GridLayout(1, false));
useDefaultsButton = new Button(nsGroup, SWT.CHECK | SWT.RIGHT);
useDefaultsButton.setText(USE_DEFAULT_LABEL);
GridData buttonData = new GridData();
buttonData.horizontalSpan = 4;
useDefaultsButton.setLayoutData(buttonData);
useDefaultsButton.setSelection(!custom);
nsUriField = createLabelAndText(nsGroup, NS_URI_FIELD_LABEL, getNsUri());
nsPrefixField = createLabelAndText(nsGroup, NS_PREFIX_FIELD_LABEL, getNsPRefix());
nsUriField.addModifyListener(nsModifyListener);
nsPrefixField.addModifyListener(nsModifyListener);
setNameSpaceGroupActivation(custom);
useDefaultsButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
boolean useDefault = useDefaultsButton.getSelection();
if (useDefault) {
updateNamespaceValues();
}
setNameSpaceGroupActivation(!useDefault);
setPageComplete(validatePage());
}
});
}
private void setNameSpaceGroupActivation(boolean enabled) {
if (nsUriField != null) {
nsUriField.setEnabled(enabled);
}
if (nsPrefixField != null) {
nsPrefixField.setEnabled(enabled);
}
}
private void updateNamespaceValues() {
if (useDefaultsButton != null && useDefaultsButton.getSelection()) {
String packageName = getPackageName();
if (nsPrefixField != null) {
nsPrefixField.setText(packageName);
}
if (nsUriField != null) {
nsUriField.setText(getDefaultNsUri(packageName));
}
}
}
private Text createLabelAndText(Composite parent, String label, String initialValue) {
Composite group = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
group.setLayout(layout);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// label
Label labelField = new Label(group, SWT.NONE);
labelField.setText(label);
labelField.setFont(parent.getFont());
// text
Text textField = new Text(group, SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = 250;
textField.setLayoutData(data);
textField.setFont(parent.getFont());
if (initialValue != null) {
textField.setText(initialValue);
}
return textField;
}
public EPackage getEPackage() {
if (ePackage == null) {
initEPackage();
}
return ePackage;
}
private void initEPackage() {
EClass eClass = (EClass) EcorePackage.eINSTANCE.getEClassifier("EPackage");
EObject rootObject = EcoreFactory.eINSTANCE.create(eClass);
if (rootObject instanceof EPackage) {
ePackage = (EPackage) rootObject;
updateEPackage(ePackage);
}
}
private void updateEPackage(EPackage p) {
p.setName(getPackageName());
p.setNsPrefix(getNsPRefix());
p.setNsURI(getNsUri());
}
/**
* Returns whether this page's controls currently all contain valid
* values.
*
* @return <code>true</code> if all controls are valid, and
* <code>false</code> if at least one is invalid
*/
protected boolean validatePage() {
if (ePackage == null) {
initEPackage();
} else {
updateEPackage(ePackage);
}
EcoreValidator validator = new EcoreValidator();
BasicDiagnostic diagnostic = new BasicDiagnostic();
boolean validName = validator.validateENamedElement_WellFormedName(ePackage, diagnostic, null);
boolean validNsUri = validator.validateEPackage_WellFormedNsURI(ePackage, diagnostic, null);
boolean validNsPrefix = validator.validateEPackage_WellFormedNsPrefix(ePackage, diagnostic, null);
boolean validEPackage = validName && validNsUri && validNsPrefix;
if (validEPackage) {
setErrorMessage(null);
} else {
StringBuilder sb = new StringBuilder();
buildCompoundMessage(sb, diagnostic);
setErrorMessage(sb.toString());
}
return validEPackage;
}
private void buildCompoundMessage(StringBuilder sb, Diagnostic diagnostic) {
if (!StringUtil.isEmpty(diagnostic.getMessage()) && diagnostic.getSeverity() != Diagnostic.OK) {
sb.append(diagnostic.getMessage());
sb.append("\n");
}
for (Diagnostic child : diagnostic.getChildren()) {
buildCompoundMessage(sb, child);
}
}
private String getPackageName() {
if (packageNameField == null) {
return DEFAULT_COMMON_FILE_NAME;
}
return packageNameField.getText().trim();
}
private String getNsUri() {
if (nsUriField == null) {
return getDefaultNsUri(getPackageName());
}
return nsUriField.getText().trim();
}
private String getDefaultNsUri(String packageName) {
return DEFAULT_URI_BASE + packageName;
}
private String getNsPRefix() {
if (nsPrefixField == null) {
return getPackageName();
}
return nsPrefixField.getText().trim();
}
public String getRepresentationFileName() {
return getPackageName() + "." + SiriusUtil.SESSION_RESOURCE_EXTENSION; //$NON-NLS-1$
}
public String getEcoreFileName() {
return getPackageName() + ".ecore"; //$NON-NLS-1$
}
public String getGenModelFileName() {
return getPackageName() + ".genmodel"; //$NON-NLS-1$
}
}
}