Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCamille Letavernier2020-12-02 10:23:09 +0000
committerCamille Letavernier2020-12-16 10:07:50 +0000
commitc2e8e12dadfed2b3243898ac7164b6c1fac5fed1 (patch)
tree99094982fa50a9661914287677dc30f2e67b1bde
parent658d4ba2ef2e72ab7866fefcdc129a8ae00fdb8e (diff)
downloadorg.eclipse.papyrus-bugs/569354-typesGeneration.tar.gz
org.eclipse.papyrus-bugs/569354-typesGeneration.tar.xz
org.eclipse.papyrus-bugs/569354-typesGeneration.zip
Bug 569354: [Toolsmiths] ElementTypes generation from a Profile shouldbugs/569354-typesGeneration
rely on the new concepts https://bugs.eclipse.org/bugs/show_bug.cgi?id=569354 - Move the plug-in metadata generation from the Profile-to-Types Wizard to a headless Generator - The generator can now also be used for existing element type models Change-Id: I42c1c8670c52da0f4b1b25caea96b2b4c6e302b1 Signed-off-by: Camille Letavernier <cletavernier@eclipsesource.com>
-rw-r--r--plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/META-INF/MANIFEST.MF3
-rw-r--r--plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/src/org/eclipse/papyrus/uml/profile/types/generator/ui/internal/wizards/GeneratorWizard.java127
-rw-r--r--plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/META-INF/MANIFEST.MF6
-rw-r--r--plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/src/org/eclipse/papyrus/toolsmiths/types/generator/TypesPluginGenerator.java275
4 files changed, 285 insertions, 126 deletions
diff --git a/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/META-INF/MANIFEST.MF b/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/META-INF/MANIFEST.MF
index 5b803616b8e..60e4c55283a 100644
--- a/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/META-INF/MANIFEST.MF
+++ b/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/META-INF/MANIFEST.MF
@@ -12,7 +12,8 @@ Require-Bundle: org.eclipse.emf.databinding;bundle-version="[1.5.0,2.0.0)",
org.eclipse.papyrus.uml.profile.types.generator;bundle-version="[3.0.0,4.0.0)",
org.eclipse.uml2.uml.editor;bundle-version="[5.5.0,6.0.0)",
org.eclipse.xtend.lib;bundle-version="[2.22.0,3.0.0)",
- org.eclipse.papyrus.eclipse.project.editors;bundle-version="[3.0.0,4.0.0)"
+ org.eclipse.papyrus.eclipse.project.editors;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.papyrus.toolsmiths;bundle-version="[2.0.0,3.0.0)"
Export-Package: org.eclipse.papyrus.uml.profile.types.generator.ui.internal,
org.eclipse.papyrus.uml.profile.types.generator.ui.internal.handlers,
org.eclipse.papyrus.uml.profile.types.generator.ui.internal.wizards;x-friends:="org.eclipse.papyrus.uml.profile.assistants.generator.ui"
diff --git a/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/src/org/eclipse/papyrus/uml/profile/types/generator/ui/internal/wizards/GeneratorWizard.java b/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/src/org/eclipse/papyrus/uml/profile/types/generator/ui/internal/wizards/GeneratorWizard.java
index 60faa12a354..8a4fe8a0edb 100644
--- a/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/src/org/eclipse/papyrus/uml/profile/types/generator/ui/internal/wizards/GeneratorWizard.java
+++ b/plugins/toolsmiths/assistants/org.eclipse.papyrus.uml.profile.types.generator.ui/src/org/eclipse/papyrus/uml/profile/types/generator/ui/internal/wizards/GeneratorWizard.java
@@ -18,13 +18,10 @@ package org.eclipse.papyrus.uml.profile.types.generator.ui.internal.wizards;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.Callable;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -36,8 +33,8 @@ import org.eclipse.jface.dialogs.DialogSettings;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.osgi.util.NLS;
-import org.eclipse.papyrus.eclipse.project.editors.project.PluginEditor;
import org.eclipse.papyrus.infra.ui.util.UIUtil;
+import org.eclipse.papyrus.toolsmiths.types.generator.TypesPluginGenerator;
import org.eclipse.papyrus.uml.profile.types.generator.AbstractGenerator;
import org.eclipse.papyrus.uml.profile.types.generator.ElementTypesGenerator;
import org.eclipse.papyrus.uml.profile.types.generator.Identifiers;
@@ -47,11 +44,9 @@ import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.uml2.uml.Profile;
-import org.w3c.dom.Element;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import com.google.common.util.concurrent.Futures;
/**
@@ -65,10 +60,6 @@ public class GeneratorWizard extends Wizard {
// FIXME : should be provided by an element type plugin
private static final String ELEMENTTYPESCONFIGURATIONS = "elementtypesconfigurations"; //$NON-NLS-1$
- public static final String TYPES_CORE_PLUGIN = "org.eclipse.papyrus.infra.types.core";
- public static final String TYPES_CORE_PLUGIN_MIN = "5.0.0";
- public static final String TYPES_CORE_PLUGIN_MAX = "6.0.0";
-
private final IWorkbenchPage page;
private final GeneratorWizardModel model;
@@ -216,118 +207,8 @@ public class GeneratorWizard extends Wizard {
return new Status(IStatus.WARNING, getClass(), "The target model is not located in a workspace project; impossible to configure the plug-in.");
}
- String projectName = outputModelURI.segment(1);
- IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
- if (!project.exists()) {
- return new Status(IStatus.WARNING, getClass(), "The target model is not located in a workspace project; impossible to configure the plug-in.");
- }
-
- if (!project.isOpen()) {
- try {
- project.open(null);
- } catch (CoreException e) {
- Activator.log.error(e);
- return new Status(IStatus.WARNING, getClass(), "The target model is located in a workspace project that couldn't be opened; impossible to configure the plug-in.");
- }
- }
-
- try {
- PluginEditor editor = new PluginEditor(project);
- editor.init();
-
- if (!editor.exists()) {
- return new Status(IStatus.WARNING, getClass(), "The target model is not located in an Eclipse Plug-in Project; impossible to configure the plug-in.");
- }
-
- Set<String> files = Sets.newHashSet(PluginEditor.BUILD_PROPERTIES_FILE, PluginEditor.PLUGIN_XML_FILE);
- addDependencies(editor);
- addExtensions(editor, outputModelURI, identifiers);
- addBuildProperties(editor, outputModelURI);
-
- editor.save();
- } catch (Exception ex) {
- return new Status(IStatus.WARNING, getClass(), "The target model is not located in an Eclipse Plug-in Project; impossible to configure the plug-in.", ex);
- }
-
- return Status.OK_STATUS;
- }
-
- /**
- * Add required plug-in dependencies to the target plug-in
- *
- * @param editor
- * The plug-in to configure
- */
- protected void addDependencies(PluginEditor editor) {
- if (!editor.hasDependency(TYPES_CORE_PLUGIN)) {
- editor.addDependency(TYPES_CORE_PLUGIN, String.format("[%s, %s)", TYPES_CORE_PLUGIN_MIN, TYPES_CORE_PLUGIN_MAX));
- }
- // TODO Find and Add dependencies to plug-ins contributing the referenced models (e.g. UML, extended profiles)
- }
-
- /**
- * Add required contributions to extension points in the target plug-in,
- * for the given element types model.
- *
- * @param editor
- * The plug-in to configure
- * @param outputModelURI
- * The generated model being contributed
- */
- protected void addExtensions(PluginEditor editor, URI outputModelURI, Identifiers identifiers) {
- if (!editor.pluginManifestExists()) {
- editor.getPluginEditor().create();
- }
- editor.addToBuild("plugin.xml");
-
- Element ext = editor.addExtension("org.eclipse.papyrus.infra.types.core.elementTypeSetConfiguration");
- Element elementTypeSet = editor.addChild(ext, "elementTypeSet");
- elementTypeSet.setAttribute("path", toLocalProjectPath(outputModelURI).toString());
- elementTypeSet.setAttribute("clientContextID", identifiers.getContextId());
- }
-
- /**
- * Add required build.properties entries in the target plug-in, for the
- * model being generated.
- *
- * @param editor
- * The plug-in to configure
- * @param outputModelURI
- * The generated model
- */
- protected void addBuildProperties(PluginEditor editor, URI outputModelURI) {
- IPath path = toLocalProjectPath(outputModelURI);
-
- // Trim one segment to exclude the file name (we always export the parent folder),
- // and convert to a workspace-relative path
- path = path.removeLastSegments(1);
-
- // Add trailing / because we export a folder
- editor.addToBuild(path.toString() + "/");
- }
-
- /**
- * <p>
- * Converts a platform:/resource/ {@link URI} to a path relative
- * to the current project.
- * </p>
- * <p>
- * The <code>platform:/resource/projectName/folderName/fileName.fileExtension</code> {@link URI}
- * becomes a <code>folderName/fileName.fileExtension</code> {@link IPath}.
- * </p>
- *
- * @param outputModelURI
- * The URI to convert to a local project path
- * @return
- * The {@link IPath} relative to the Project Root, corresponding to this URI
- */
- protected IPath toLocalProjectPath(URI outputModelURI) {
- IPath path = new Path(outputModelURI.toPlatformString(true));
-
- // Remove the project name, as we export paths relative to the project folder
- path = path.removeFirstSegments(1);
-
- return path;
+ IPath modelPath = new Path(outputModelURI.toPlatformString(true));
+ return new TypesPluginGenerator().generate(Collections.singleton(modelPath), identifiers.getContextId());
}
protected void addGenerators(List<? super AbstractGenerator<Profile, ?>> generators, Identifiers identifiers, GeneratorWizardModel wizardModel) {
diff --git a/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/META-INF/MANIFEST.MF b/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/META-INF/MANIFEST.MF
index fcbe3480ade..3e3d422943d 100644
--- a/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/META-INF/MANIFEST.MF
+++ b/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/META-INF/MANIFEST.MF
@@ -13,13 +13,15 @@ Require-Bundle: org.eclipse.draw2d;bundle-version="[3.10.0,4.0.0)",
org.eclipse.pde.ui;bundle-version="[3.11.0,4.0.0)",
org.eclipse.ui.ide;bundle-version="[3.17.0,4.0.0)",
org.eclipse.ui.views.properties.tabbed;bundle-version="[3.8.0,4.0.0)",
- org.eclipse.uml2.types;bundle-version="[2.5.0,3.0.0)"
+ org.eclipse.uml2.types;bundle-version="[2.5.0,3.0.0)",
+ com.google.guava;bundle-version="[21.0.0,28.0.0)"
Export-Package: org.eclipse.papyrus.toolsmiths.factory,
org.eclipse.papyrus.toolsmiths.generator,
org.eclipse.papyrus.toolsmiths.model.customizationplugin,
org.eclipse.papyrus.toolsmiths.model.customizationplugin.impl,
org.eclipse.papyrus.toolsmiths.model.customizationplugin.util,
- org.eclipse.papyrus.toolsmiths.plugin
+ org.eclipse.papyrus.toolsmiths.plugin,
+ org.eclipse.papyrus.toolsmiths.types.generator
Bundle-Vendor: %providerName
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
diff --git a/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/src/org/eclipse/papyrus/toolsmiths/types/generator/TypesPluginGenerator.java b/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/src/org/eclipse/papyrus/toolsmiths/types/generator/TypesPluginGenerator.java
new file mode 100644
index 00000000000..e7831118939
--- /dev/null
+++ b/plugins/toolsmiths/org.eclipse.papyrus.toolsmiths/src/org/eclipse/papyrus/toolsmiths/types/generator/TypesPluginGenerator.java
@@ -0,0 +1,275 @@
+/*****************************************************************************
+ * Copyright (c) 2020 EclipseSource and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Camille Letavernier - Bug 569354
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.toolsmiths.types.generator;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.papyrus.eclipse.project.editors.project.PluginEditor;
+import org.eclipse.papyrus.toolsmiths.Activator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * <p>
+ * Generates the plug-in metadata from an *.elementtypesconfiguration model.
+ * </p>
+ *
+ * <p>
+ * Supported artifacts:
+ * <ul>
+ * <li>build.properties</li>
+ * <li>plugin.xml</li>
+ * <li>MANIFEST.MF</li>
+ * </ul>
+ * </p>
+ */
+public class TypesPluginGenerator {
+
+ public static final String TYPES_CORE_PLUGIN = "org.eclipse.papyrus.infra.types.core";
+ public static final String TYPES_CORE_PLUGIN_MIN = "5.0.0";
+ public static final String TYPES_CORE_PLUGIN_MAX = "6.0.0";
+
+ // Element Type Extension Point
+ private static final String EXTENSION_POINT = "org.eclipse.papyrus.infra.types.core.elementTypeSetConfiguration";
+ private static final String ELEMENT_TYPE_SET = "elementTypeSet";
+ private static final String CLIENT_CONTEXT_ID = "clientContextID";
+ private static final String PATH = "path";
+
+ /**
+ * <p>
+ * Configure the plug-ins owning the target models (e.g. Add necessary dependencies
+ * to Papyrus ElementTypes framework, as well a required ElementType plug-in dependencies,
+ * ensure build.properties contains all the necessary resources...).
+ * </p>
+ *
+ * <p>
+ * For target projects that are not an Eclipse plug-in project, this method does nothing and returns a warning.
+ * </p>
+ *
+ * @param modelPaths
+ * The collection of paths. Each path represents an elementtypeconfiguration model.
+ * @param contextId
+ * The clientContextID for which the type models should be registered. For Papyrus, this is usually
+ * <code>org.eclipse.papyrus.infra.services.edit.TypeContext</code>, but this may vary in some
+ * specific applications / customization scenarios.
+ * @return
+ * The status representing the result of this configuration operation.
+ */
+ public IStatus generate(Collection<IPath> elementTypesConfigurationModels, String contextId) {
+ Map<IProject, Collection<IPath>> paths = groupByProject(elementTypesConfigurationModels);
+ for (var entry : paths.entrySet()) {
+ IProject project = entry.getKey();
+ IStatus configurePlugin = configurePlugin(project, entry.getValue(), contextId);
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * <p>
+ * Configure the plug-in owning the target model (e.g. Add necessary dependencies
+ * to Papyrus ElementTypes framework, as well a required ElementType plug-in dependencies,
+ * ensure build.properties contains all the necessary resources...).
+ * </p>
+ *
+ * <p>
+ * If the target project is not an Eclipse plug-in project, this method does nothing and returns a warning.
+ * </p>
+ *
+ * @param project
+ * The project containing the models
+ * @param modelPaths
+ * The collection of paths. Each path represents an elementtypeconfiguration model
+ * @param contextId
+ * The clientContextID for which the type models should be registered. For Papyrus, this is usually
+ * <code>org.eclipse.papyrus.infra.services.edit.TypeContext</code>, but this may vary in some
+ * specific applications / customization scenarios.
+ * @return
+ * The status representing the result of this configuration operation.
+ */
+ protected IStatus configurePlugin(IProject project, Collection<IPath> modelPaths, String contextId) {
+ // Should always be a workspace project; but let's make sure
+ // if (!modelPath.isPlatformResource()) {
+ // return new Status(IStatus.WARNING, getClass(), "The target model is not located in a workspace project; impossible to configure the plug-in.");
+ // }
+
+ if (!project.exists()) {
+ return new Status(IStatus.WARNING, getClass(), "The target model is not located in a workspace project; impossible to configure the plug-in.");
+ }
+
+ if (!project.isOpen()) {
+ try {
+ project.open(null);
+ } catch (CoreException e) {
+ Activator.log.error(e);
+ return new Status(IStatus.WARNING, getClass(), "The target model is located in a workspace project that couldn't be opened; impossible to configure the plug-in.");
+ }
+ }
+
+ try {
+ PluginEditor editor = new PluginEditor(project);
+ editor.init();
+
+ if (!editor.exists()) {
+ return new Status(IStatus.WARNING, getClass(), "The target model is not located in an Eclipse Plug-in Project; impossible to configure the plug-in.");
+ }
+
+ addDependencies(editor);
+ addExtensions(editor, modelPaths, contextId);
+ for (IPath path : modelPaths) {
+ addBuildProperties(editor, path);
+ }
+
+ editor.save();
+ } catch (Exception ex) {
+ return new Status(IStatus.WARNING, getClass(), "The target model is not located in an Eclipse Plug-in Project; impossible to configure the plug-in.", ex);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Add required plug-in dependencies to the target plug-in
+ *
+ * @param editor
+ * The plug-in to configure
+ */
+ protected void addDependencies(PluginEditor editor) {
+ if (!editor.hasDependency(TYPES_CORE_PLUGIN)) {
+ editor.addDependency(TYPES_CORE_PLUGIN, String.format("[%s, %s)", TYPES_CORE_PLUGIN_MIN, TYPES_CORE_PLUGIN_MAX));
+ }
+ // TODO Find and Add dependencies to plug-ins contributing the referenced models (e.g. UML, extended profiles)
+ }
+
+ /**
+ * Add required contributions to extension points in the target plug-in,
+ * for the given element types model.
+ *
+ * @param editor
+ * The plug-in to configure.
+ * @param modelPaths
+ * The models to add to the extensions.
+ * @param contextId
+ * The clientContextID for which the type model should be registered.
+ */
+ protected void addExtensions(PluginEditor editor, Collection<IPath> modelPaths, String contextId) {
+ if (!editor.pluginManifestExists()) {
+ editor.getPluginEditor().create();
+ }
+ editor.addToBuild("plugin.xml");
+
+ // Identify the missing paths. Convert the IPath to the String-format used in the extension point
+ Set<String> missingPaths = modelPaths.stream() //
+ .map(this::toLocalProjectPath) //
+ .map(IPath::toString) //
+ .collect(Collectors.toSet());
+
+ // Check if the extension(s) already exist(s).
+ List<Node> extensions = editor.getExtensions(EXTENSION_POINT);
+ for (Node extension : extensions) {
+ NodeList childNodes = extension.getChildNodes();
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node childNode = childNodes.item(i);
+ if (childNode.getNodeType() == Node.ELEMENT_NODE && ELEMENT_TYPE_SET.equals(childNode.getNodeName())) {
+ Element childElement = (Element) childNode;
+ if (contextId.equals(childElement.getAttribute(CLIENT_CONTEXT_ID)) && childElement.hasAttribute(PATH)) {
+ missingPaths.remove(childElement.getAttribute(PATH));
+ }
+ }
+ }
+ }
+
+ for (String modelPath : missingPaths) {
+ Element ext = editor.addExtension(EXTENSION_POINT);
+ Element elementTypeSet = editor.addChild(ext, ELEMENT_TYPE_SET);
+ elementTypeSet.setAttribute(PATH, modelPath);
+ elementTypeSet.setAttribute(CLIENT_CONTEXT_ID, contextId);
+ }
+ }
+
+ /**
+ * Add required build.properties entries in the target plug-in, for the
+ * model being generated.
+ *
+ * @param editor
+ * The plug-in to configure
+ * @param modelPath
+ * The element types model path
+ */
+ protected void addBuildProperties(PluginEditor editor, IPath modelPath) {
+ IPath path = toLocalProjectPath(modelPath);
+
+ // Trim one segment to exclude the file name (we always export the parent folder),
+ // and convert to a workspace-relative path
+ path = path.removeLastSegments(1);
+
+ // Add trailing / because we export a folder
+ editor.addToBuild(path.toString() + "/");
+ }
+
+
+ /**
+ * <p>
+ * Converts a workspace {@link IPath} to a path relative
+ * to the current project.
+ * </p>
+ * <p>
+ * The <code>/projectName/folderName/fileName.fileExtension</code> {@link IPath}
+ * becomes <code>folderName/fileName.fileExtension</code>.
+ * </p>
+ *
+ * @param modelPath
+ * The IPath to convert to a local project path
+ * @return
+ * The {@link IPath} relative to the Project Root, corresponding to this URI
+ */
+ protected IPath toLocalProjectPath(IPath modelPath) {
+ // Remove the project name, as we export paths relative to the project folder
+ IPath path = modelPath.removeFirstSegments(1);
+
+ return path;
+ }
+
+ private Map<IProject, Collection<IPath>> groupByProject(Collection<IPath> elementTypesConfigurationModels) {
+ Map<IProject, Collection<IPath>> result = new HashMap<>();
+
+ for (IPath configPath : elementTypesConfigurationModels) {
+ result.computeIfAbsent(getProject(configPath), project -> new ArrayList<>()).add(configPath);
+ }
+
+ return result;
+ }
+
+ private IProject getProject(IPath path) {
+ if (path.segmentCount() == 0) {
+ return null;
+ }
+ IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+ return root.getProject(path.segment(0));
+ }
+}

Back to the top