/******************************************************************************* * Copyright (c) 2015-2016 Obeo, Inria * 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: * - William Piers <william.piers@obeo.fr> * - Philippe Merle <philippe.merle@inria.fr> *******************************************************************************/ package org.occiware.clouddesigner.occi.design.wizard; import java.io.ByteArrayInputStream; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.pde.internal.core.project.PDEProject; import org.eclipse.pde.internal.ui.wizards.tools.ConvertProjectToPluginOperation; import org.eclipse.sirius.business.api.modelingproject.ModelingProject; import org.eclipse.sirius.ui.tools.api.project.ModelingProjectManager; 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.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.WizardNewProjectCreationPage; import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; import org.occiware.clouddesigner.occi.OCCIRegistry; import org.occiware.clouddesigner.occi.OcciCoreConstants; import org.occiware.clouddesigner.occi.design.Activator; import org.occiware.clouddesigner.occi.design.Messages; import org.occiware.clouddesigner.occi.design.utils.WizardUtils; import com.google.common.base.Strings; /** * The wizard to create a new Extension designer project. * * @author William Piers * <a href="mailto:william.piers@obeo.fr">william.piers@obeo.fr</a> * @author Philippe Merle * <a href="mailto:philippe.merle@inria.fr">philippe.merle@inria.fr</a> */ public class NewExtensionWizard extends BasicNewProjectResourceWizard { private static final String EXTENSION_DIAGRAM_NAME = "Extension diagram"; //$NON-NLS-1$ protected static final String EXTENSION_FILEEXT = "occie"; //$NON-NLS-1$ private CheckboxTableViewer refExtensionViewer; private final class NewExtensionWizardPage extends WizardNewProjectCreationPage { private NewExtensionWizardPage(String pageName) { super(pageName); } @Override public void createControl(Composite parent) { super.createControl(parent); Composite control = (Composite) getControl(); Composite extensionGroup = new Composite(control, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; extensionGroup.setLayout(layout); extensionGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); Label projectLabel = new Label(extensionGroup, SWT.NONE); projectLabel.setText(Messages.NewExtensionWizard_ExtensionNameLabel); projectLabel.setFont(parent.getFont()); extensionNameText = new Text(extensionGroup, SWT.BORDER); GridData data = new GridData(GridData.FILL_HORIZONTAL); extensionNameText.setLayoutData(data); extensionNameText.setFont(parent.getFont()); extensionNameText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { extensionName = extensionNameText.getText(); setPageComplete(validatePage()); } }); Label schemeLabel = new Label(extensionGroup, SWT.NONE); schemeLabel.setText(Messages.NewExtensionWizard_ExtensionSchemeLabel); schemeLabel.setFont(parent.getFont()); extensionSchemeText = new Text(extensionGroup, SWT.BORDER); GridData data1 = new GridData(GridData.FILL_HORIZONTAL); extensionSchemeText.setLayoutData(data1); extensionSchemeText.setFont(parent.getFont()); extensionSchemeText.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { extensionScheme = extensionSchemeText.getText(); if (!extensionScheme.endsWith("#")) { extensionScheme += "#"; } setPageComplete(validatePage()); } }); Label refOccieLabel = new Label(extensionGroup, SWT.NONE); refOccieLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true)); refOccieLabel.setText(Messages.NewExtensionWizard_RefExtensionLabel); refOccieLabel.setFont(parent.getFont()); Composite composite = new Composite(extensionGroup, SWT.NULL); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); composite.setLayoutData(layoutData); TableColumnLayout tableLayout = new TableColumnLayout(); composite.setLayout(tableLayout); Table table = new Table(composite, SWT.CHECK | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL); refExtensionViewer = new CheckboxTableViewer(table); refExtensionViewer.setContentProvider(ArrayContentProvider.getInstance()); Collection<String> registeredExtensions = new ArrayList<String>( OCCIRegistry.getInstance().getRegisteredExtensions()); // added by default registeredExtensions.remove(OcciCoreConstants.OCCI_CORE_SCHEME); refExtensionViewer.setInput(registeredExtensions); } @Override protected boolean validatePage() { // TODO add error messages return super.validatePage() && !Strings.isNullOrEmpty(extensionNameText.getText().trim()) && !Strings.isNullOrEmpty(extensionSchemeText.getText().trim()); } } /** * project. */ protected IProject project; protected NewExtensionWizardPage newProjectPage; /** * Name of the Extension. */ protected String extensionName; private Text extensionNameText; /** * Scheme of the Extension. */ protected String extensionScheme; private Text extensionSchemeText; /** * Create a default model then select it in the explorer and switch to * modeling perspective. The project, the rootObjectName and the * newUmlModelFileName must be initialized before calling the performFinish * method. {@inheritDoc} */ @Override public boolean performFinish() { try { getContainer().run(false, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { project = ModelingProjectManager.INSTANCE.createNewModelingProject( newProjectPage.getProjectName(), newProjectPage.getLocationPath(), true, monitor); ModelingProject.asModelingProject(project).get().getSession().getSelectedViewpoints(false); } catch (CoreException e) { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.NewExtensionWizard_ProjectCreationError, e)); } if (project == null || extensionName == null || extensionScheme == null) { throw new IllegalArgumentException(); } final IRunnableWithProgress op = new WorkspaceModifyOperation(null) { @Override protected void execute(IProgressMonitor monitor) throws CoreException, InterruptedException { final InitExtensionModel init = new InitExtensionModel(project, extensionName, extensionScheme, WizardUtils.getRefExtensionSchemes(refExtensionViewer)); try { getContainer().run(false, true, init); } catch (final InterruptedException e) { // Ignore. } catch (final InvocationTargetException e) { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.NewExtensionWizard_ModelCreationError, e)); } // Register this new OCCI extension. OCCIRegistry.getInstance().registerExtension(extensionScheme, init.getSemanticModelURI().toString()); // Get the newly created file final IResource newModelFile = project.findMember("/model/" //$NON-NLS-1$ + extensionName.toLowerCase() + "." + NewExtensionWizard.EXTENSION_FILEEXT); selectAndReveal(newModelFile, PlatformUI.getWorkbench().getActiveWorkbenchWindow()); // Switch to the modeling perspective // updatePerspective(); PlatformUI.getWorkbench().showPerspective(WizardUtils.MODELING_PERSPECTIVE_ID, PlatformUI.getWorkbench().getActiveWorkbenchWindow()); WizardUtils.openDiagram(monitor, project, EXTENSION_DIAGRAM_NAME, extensionName, WizardUtils.getRoot(ModelingProject.asModelingProject(project).get().getSession(), init.getSemanticModelURI())); } }; try { // create modeling project getContainer().run(false, true, op); // convert to plugin project getContainer().run(false, true, new ConvertProjectToPluginOperation(new IProject[] { project }, false)); // add XText nature for using OCCI XText Editor. WizardUtils.addXTextNature(project, monitor); project.refreshLocal(IResource.DEPTH_INFINITE, monitor); // convert to OCCIE plugin getContainer().run(false, true, new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { configureOCCIEExtension(monitor); } }); project.refreshLocal(IResource.DEPTH_INFINITE, monitor); } catch (final InvocationTargetException e) { if (e.getTargetException() instanceof CoreException) { ErrorDialog.openError(getContainer().getShell(), Messages.NewExtensionWizard_ModelCreationError, null, ((CoreException) e.getTargetException()).getStatus()); } else { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, Messages.NewExtensionWizard_ModelCreationError, e)); } } catch (CoreException | InterruptedException e) { Activator.getDefault().getLog() .log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } } }); } catch (InvocationTargetException | InterruptedException e) { Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e)); } return true; } private void configureOCCIEExtension(IProgressMonitor monitor) throws CoreException { IFile manifest = PDEProject.getManifest(project); String manifestContent = "Manifest-Version: 1.0\n" + "Bundle-ManifestVersion: 2\n" + "Bundle-Name: " + project.getName() + "\n" + "Bundle-SymbolicName: " + project.getName() + ";singleton:=true\n" + "Bundle-Version: 1.0.0.qualifier\n" + "Bundle-ClassPath: .\n" + "Bundle-Vendor: OCCIware\n" + // "Bundle-Localization: plugin\n" + // FIXME: require to generate plugin.properties "Bundle-RequiredExecutionEnvironment: JavaSE-1.7\n" + "Bundle-ActivationPolicy: lazy\n" + "Require-Bundle: org.eclipse.emf.ecore;visibility:=reexport,\n" + " org.occiware.clouddesigner.occi;visibility:=reexport,\n" + " org.occiware.clouddesigner.occi.emfgen.ui\n"; manifest.setContents(new ByteArrayInputStream(manifestContent.getBytes()), true, false, monitor); IFile pluginXML = PDEProject.getPluginXml(project); String pluginContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<?eclipse version=\"3.0\"?>\n" + "<!--\n" + " Copyright (c) 2015-2016 Obeo, Inria\n" + " All rights reserved. This program and the accompanying materials\n" + " are made available under the terms of the Eclipse Public License v1.0\n" + " which accompanies this distribution, and is available at\n" + " http://www.eclipse.org/legal/epl-v10.html\n" + "\n" + " Contributors:\n" + " - William Piers <william.piers@obeo.fr>\n" + " - Philippe Merle <philippe.merle@inria.fr>\n" + "-->\n" + "<plugin>\n" + "\n" + " <!-- Register the " + extensionName + " extension. -->\n" + " <extension point=\"org.occiware.clouddesigner.occi.occie\">\n" + " <occie scheme=\"" + extensionScheme + "\" file=\"model/" + extensionName + ".occie\"/>\n" + " </extension>\n" + "\n" + " <!-- Define URI mapping. -->\n" + " <extension point=\"org.eclipse.emf.ecore.uri_mapping\">\n" + " <mapping source=\"" + extensionScheme.substring(0,extensionScheme.length()-1) + "\" target=\"platform:/plugin/" + project.getName() + "/model/" + extensionName + ".occie\"/>\n" + " </extension>\n" + "\n" + " <!-- Register the parser for ." + extensionName + " files. -->\n" + " <extension point=\"org.eclipse.emf.ecore.extension_parser\">\n" + " <parser type=\"" + extensionName + "\" class=\"org.occiware.clouddesigner.occi.util.OCCIResourceFactoryImpl\"/>\n" + " </extension>\n" + "\n" + " <!-- Popup menu for converting to an OCCI Configuration file. -->\n" + " <extension point=\"org.eclipse.ui.popupMenus\">\n" + " <objectContribution\n" + " id=\"" + newProjectPage.getProjectName() + ".contribution\"\n" + " nameFilter=\"*." + extensionName +"\"\n" + " objectClass=\"org.eclipse.core.resources.IFile\">\n" + " <menu\n" + " id=\"org.occiware.clouddesigner.menu\"\n" + " label=\"Cloud Designer\"\n" + " path=\"additionsCloudDesigner\">\n" + " <separator name=\"group\"/>\n" + " </menu>\n" + " <action\n" + " class=\"org.occiware.clouddesigner.occi.emfgen.ui.popup.actions.Ecore2OCCIAction\"\n" + " enablesFor=\"1\"\n" + " id=\"" + newProjectPage.getProjectName() + ".ecore2occi\"\n" + " label=\"Convert to an OCCI Configuration File\"\n" + " menubarPath=\"org.occiware.clouddesigner.menu/group\">\n" + " </action>\n" + " </objectContribution>\n" + " </extension>\n" + "</plugin>\n"; pluginXML.create(new ByteArrayInputStream(pluginContent.getBytes()), true, monitor); IFile build = PDEProject.getBuildProperties(project); String buildContent = "# Copyright (c) 2015-2016 Obeo, Inria\n" + "# All rights reserved. This program and the accompanying materials\n" + "# are made available under the terms of the Eclipse Public License v1.0\n" + "# which accompanies this distribution, and is available at\n" + "# http://www.eclipse.org/legal/epl-v10.html\n" + "#\n" + "# Contributors:\n" + "# - William Piers <william.piers@obeo.fr>\n" + "# - Philippe Merle <philippe.merle@inria.fr>\n" + "\n" + "source.. = src-gen/\n" + "jars.compile.order = .\n" + "output.. = bin/\n" + "bin.includes = .,\\\n" + " model/,\\\n" + " META-INF/,\\\n" + " plugin.xml,\\\n" + " plugin.properties\n"; build.setContents(new ByteArrayInputStream(buildContent.getBytes()), true, false, monitor); } @Override public void addPages() { // we're not calling the super as we want to control the project // creation, we don't want the default // page. // super.addPages(); newProjectPage = new NewExtensionWizardPage(Messages.NewExtensionWizard_PageName); newProjectPage.setInitialProjectName(""); //$NON-NLS-1$ newProjectPage.setTitle(Messages.NewExtensionWizard_PageTitle); newProjectPage.setDescription(Messages.NewExtensionWizard_PageDescription); addPage(newProjectPage); } }