Bug 567792 - [Robotics, ROS2] Avoid (temporary) model transformation

- Do not apply the ExecutionTransformationChain via a command.
- Execute transformation chain directly for normal code generation, code generation
  with CDT settings, and generation in the context of opening a CDT editor
- New TransformationUtils class replaces the PrepareCodegenCmd
- Do not open CDT editor on systems

Change-Id: I2a538b993cb35fda169ce089517572ebcdc544e6
Signed-off-by: Ansgar Radermacher <ansgar.radermacher@cea.fr>
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/plugin.xml b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/plugin.xml
index d2d1e92..aad3555 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/plugin.xml
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/plugin.xml
@@ -25,7 +25,6 @@
 							<or>
 								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::ComponentDefinition"/>
 								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::Activity"/>
-								<test property="org.eclipse.papyrus.uml.stereotype" value="robotics::components::System"/>
 							</or>
 						</adapt>
 					</iterate>
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsModelToCDT.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsModelToCDT.java
index 7257ce8..db0462f 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsModelToCDT.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsModelToCDT.java
@@ -31,11 +31,10 @@
 import org.eclipse.papyrus.designer.languages.common.extensionpoints.LanguageCodegen;
 import org.eclipse.papyrus.designer.languages.cpp.codegen.Constants;
 import org.eclipse.papyrus.designer.transformation.base.utils.ProjectManagement;
-import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain;
 import org.eclipse.papyrus.infra.core.Activator;
 import org.eclipse.papyrus.robotics.ros2.cdteditor.TextEditorConstants;
-import org.eclipse.papyrus.robotics.ros2.codegen.commands.PrepareCodegenCmd;
 import org.eclipse.papyrus.robotics.ros2.codegen.utils.PackageTools;
+import org.eclipse.papyrus.robotics.ros2.codegen.utils.TransformationUtils;
 import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
 import org.eclipse.ui.progress.UIJob;
 import org.eclipse.uml2.uml.Class;
@@ -61,50 +60,46 @@
 			return null;
 		}
 
-		Package pkg = PackageUtil.getRootPackage((Class) classifier);
-		PrepareCodegenCmd prepareCmd = new PrepareCodegenCmd(pkg);
-		if (prepareCmd.prepare()) {
-			IProject modelProject = ProjectManagement.getCurrentProject();
+		final Package pkg = PackageUtil.getRootPackage((Class) classifier);
+		final IProject modelProject = ProjectManagement.getCurrentProject();
 
-			Job job = new UIJob("Generate ROS code") {
+		// TODO: running in UI thread, generating all files
+		Job job = new UIJob("Generate ROS code") { //$NON-NLS-1$
 
-				@Override
-				public IStatus runInUIThread(IProgressMonitor monitor) {
-					// execute the task ...
-					new ExecuteTransformationChain(pkg, modelProject).executeTransformation(monitor, 0);
-					prepareCmd.undo();
-					return Status.OK_STATUS;
-				}
-			};
-			job.setUser(true);
-			job.schedule();
-
-			ILangCodegen codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, generatorID);
-			String projectName = PackageTools.getProjectName(pkg);
-			IProject targetProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
-
-			IContainer srcPkg = null;
-			IFile cppFile = null;
-			try {
-
-				String suffix = (codegen instanceof ILangCodegen2) ? suffix = ((ILangCodegen2) codegen).getSuffix(FILE_KIND.BODY) : CPP_SUFFIX;
-
-				cppFile = targetProject.getFile(new Path(codegen.getFileName(targetProject, classifier) + Constants.DOT + suffix));
-
-				// IStorage storage = new TextStorage(string);
-			} finally {
-				// Refresh the container for the newly created files. This needs to be done even
-				// during error because of the possibility for partial results.
-				try {
-					if (srcPkg != null) {
-						srcPkg.refreshLocal(IResource.DEPTH_INFINITE, null);
-					}
-				} catch (CoreException e) {
-					Activator.log.error(e);
-				}
+			@Override
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				// execute the task ...
+				TransformationUtils.executeRosTranformation(pkg, modelProject, monitor);
+				return Status.OK_STATUS;
 			}
-			return cppFile;
+		};
+		job.setUser(true);
+		job.schedule();
+
+		ILangCodegen codegen = LanguageCodegen.getGenerator(TextEditorConstants.CPP, generatorID);
+		String projectName = PackageTools.getProjectName(pkg);
+		IProject targetProject = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
+
+		IContainer srcPkg = null;
+		IFile cppFile = null;
+		try {
+
+			String suffix = (codegen instanceof ILangCodegen2) ? suffix = ((ILangCodegen2) codegen).getSuffix(FILE_KIND.BODY) : CPP_SUFFIX;
+
+			cppFile = targetProject.getFile(new Path(codegen.getFileName(targetProject, classifier) + Constants.DOT + suffix));
+
+			// IStorage storage = new TextStorage(string);
+		} finally {
+			// Refresh the container for the newly created files. This needs to be done even
+			// during error because of the possibility for partial results.
+			try {
+				if (srcPkg != null) {
+					srcPkg.refreshLocal(IResource.DEPTH_INFINITE, null);
+				}
+			} catch (CoreException e) {
+				Activator.log.error(e);
+			}
 		}
-		return null;
+		return cppFile;
 	}
 }
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/META-INF/MANIFEST.MF b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/META-INF/MANIFEST.MF
index aaeb8ce..98dc0e3 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/META-INF/MANIFEST.MF
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/META-INF/MANIFEST.MF
@@ -1,6 +1,5 @@
 Manifest-Version: 1.0
 Export-Package: org.eclipse.papyrus.robotics.ros2.codegen,
- org.eclipse.papyrus.robotics.ros2.codegen.commands,
  org.eclipse.papyrus.robotics.ros2.codegen.launch,
  org.eclipse.papyrus.robotics.ros2.codegen.utils
 Require-Bundle: org.eclipse.ui,
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/commands/PrepareCodegenCmd.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/commands/PrepareCodegenCmd.java
deleted file mode 100644
index c6efc82..0000000
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/commands/PrepareCodegenCmd.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2020 CEA LIST
- * 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
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- *     Ansgar Radermacher (CEA LIST) - initial API and implementation
- *
- *******************************************************************************/
-
-package org.eclipse.papyrus.robotics.ros2.codegen.commands;
-
-import java.util.Stack;
-
-import org.eclipse.emf.common.command.AbstractCommand;
-import org.eclipse.emf.transaction.RecordingCommand;
-import org.eclipse.emf.transaction.TransactionalEditingDomain;
-import org.eclipse.emf.transaction.util.TransactionUtil;
-import org.eclipse.papyrus.commands.Activator;
-import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
-import org.eclipse.papyrus.designer.transformation.profile.Transformation.ExecuteTrafoChain;
-import org.eclipse.papyrus.designer.transformation.profile.Transformation.M2MTrafoChain;
-import org.eclipse.papyrus.robotics.ros2.codegen.utils.ApplyProfiles;
-import org.eclipse.papyrus.robotics.ros2.codegen.utils.Helpers;
-import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
-import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
-import org.eclipse.uml2.uml.NamedElement;
-import org.eclipse.uml2.uml.Package;
-import org.eclipse.uml2.uml.util.UMLUtil;
-
-@SuppressWarnings("nls")
-public class PrepareCodegenCmd {
-	
-	protected ExecuteTrafoChain chain;
-
-	protected Stack<AbstractCommand> appliedCmds = new Stack<AbstractCommand>();
-
-	protected Package pkg;
-
-	protected TransactionalEditingDomain domain;
-
-	public PrepareCodegenCmd(Package pkg) {
-		this.pkg = pkg;
-		domain = TransactionUtil.getEditingDomain(pkg);
-	}
-
-	public boolean prepare() {
-		chain = UMLUtil.getStereotypeApplication(pkg, ExecuteTrafoChain.class);
-		if (chain == null) {
-			RecordingCommand applyStereoCmd = new RecordingCommand(domain, "Apply ExecuteTrafoChain stereotype") {
-
-				@Override
-				protected void doExecute() {
-					chain = StereotypeUtil.applyApp(pkg, ExecuteTrafoChain.class);
-					if (chain == null) {
-						ApplyProfiles.applyTrafoProfile(pkg);
-						chain = StereotypeUtil.applyApp(pkg, ExecuteTrafoChain.class);
-					}
-				}
-			};
-			domain.getCommandStack().execute(applyStereoCmd);
-			appliedCmds.push(applyStereoCmd);
-		}
-		if (chain == null) {
-			Activator.log.debug("Can't apply TransformationChain stereotype");
-			undo();
-			return false;
-		}
-
-		if (chain.getChain() == null) {
-			RecordingCommand setChainCmd = new RecordingCommand(domain, "Set robotics chain") {
-
-				@Override
-				protected void doExecute() {
-					Package rosLibrary = PackageUtil.loadPackage(Helpers.ROS_LIBRARY_URI, domain.getResourceSet());
-					NamedElement rosChainCl = ElementUtils.getQualifiedElementFromRS(rosLibrary, "ros2Library::m2mtransformations::ROSChain");
-					if (rosChainCl != null) {
-						M2MTrafoChain rosChain = UMLUtil.getStereotypeApplication(rosChainCl, M2MTrafoChain.class);
-						chain.setChain(rosChain);
-					}
-				}
-			};
-			domain.getCommandStack().execute(setChainCmd);
-			appliedCmds.push(setChainCmd);
-		}
-		return true;
-	}
-	
-	public void undo() {
-		while (!appliedCmds.isEmpty()) {
-			appliedCmds.pop();
-			if (domain.getCommandStack().canUndo()) {
-				domain.getCommandStack().undo();
-			}
-		}
-	}
-}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/GenerateCodeHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/GenerateCodeHandler.java
index c40a184..e41362b 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/GenerateCodeHandler.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/GenerateCodeHandler.java
@@ -25,10 +25,9 @@
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.papyrus.designer.transformation.base.utils.ProjectManagement;
-import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain;
 import org.eclipse.papyrus.designer.transformation.core.transformations.TransformationContext;
 import org.eclipse.papyrus.designer.transformation.profile.Transformation.ExecuteTrafoChain;
-import org.eclipse.papyrus.robotics.ros2.codegen.commands.PrepareCodegenCmd;
+import org.eclipse.papyrus.robotics.ros2.codegen.utils.TransformationUtils;
 import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
 import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
 import org.eclipse.swt.widgets.Display;
@@ -47,27 +46,20 @@
 			return null;
 		}
 
-		Package pkg = PackageUtil.getRootPackage((Classifier) selectedEObject);
-		PrepareCodegenCmd prepareCmd = new PrepareCodegenCmd(pkg);
-		if (prepareCmd.prepare()) {
-			IProject project = ProjectManagement.getCurrentProject();
+		final Package pkg = PackageUtil.getRootPackage((Classifier) selectedEObject);
+		final IProject project = ProjectManagement.getCurrentProject();
 
-			Job job = new Job("Generate ROS code") {
+		Job job = new Job("Generate ROS code") {
 
-				@Override
-				public IStatus run(IProgressMonitor monitor) {
-					// execute the task ...
-					try {
-						new ExecuteTransformationChain(pkg, project).executeTransformation(monitor, 0);
-					} finally {
-						prepareCmd.undo();
-					}
-					return Status.OK_STATUS;
-				}
-			};
-			job.setUser(true);
-			job.schedule();
-		}
+			@Override
+			public IStatus run(IProgressMonitor monitor) {
+				// execute the task ...
+				TransformationUtils.executeRosTranformation(pkg, project, monitor);
+				return Status.OK_STATUS;
+			}
+		};
+		job.setUser(true);
+		job.schedule();
 		return null;
 	}
 
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/RewriteCDTHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/RewriteCDTHandler.java
index 880eda3..1ee89b2 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/RewriteCDTHandler.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/handlers/RewriteCDTHandler.java
@@ -27,9 +27,8 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.papyrus.designer.transformation.base.utils.ProjectManagement;
-import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain;
 import org.eclipse.papyrus.designer.transformation.profile.Transformation.ExecuteTrafoChain;
-import org.eclipse.papyrus.robotics.ros2.codegen.commands.PrepareCodegenCmd;
+import org.eclipse.papyrus.robotics.ros2.codegen.utils.TransformationUtils;
 import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
 import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
 import org.eclipse.uml2.uml.Class;
@@ -42,10 +41,10 @@
 	protected ExecuteTrafoChain chain;
 
 	protected static boolean cmdActive;
-	
+
 	// assure that project only gets rewritten once
 	protected static Map<String, Boolean> rewriteMap;
-	
+
 	@Override
 	public Object execute(ExecutionEvent arg0) throws ExecutionException {
 		updateSelectedEObject();
@@ -53,38 +52,33 @@
 			return null;
 		}
 
-		Package pkg = PackageUtil.getRootPackage((Class) selectedEObject);
-		PrepareCodegenCmd prepareCmd = new PrepareCodegenCmd(pkg);
-		if (prepareCmd.prepare()) {
-			IProject project = ProjectManagement.getCurrentProject();
+		final Package pkg = PackageUtil.getRootPackage((Class) selectedEObject);
+		final IProject project = ProjectManagement.getCurrentProject();
 
-			Job job = new Job("Generate ROS code") {
+		Job job = new Job("Generate ROS code") {
 
-				@Override
-				public IStatus run(IProgressMonitor monitor) {
-					// execute the task ...
-					rewriteMap = new HashMap<String, Boolean>();
-					cmdActive = true;
-					try {
-						new ExecuteTransformationChain(pkg, project).executeTransformation(monitor, 0);
-					}
-					finally {
-						prepareCmd.undo();
-						cmdActive = false;
-					}
-					return Status.OK_STATUS;
+			@Override
+			public IStatus run(IProgressMonitor monitor) {
+				// execute the task ...
+				rewriteMap = new HashMap<String, Boolean>();
+				cmdActive = true;
+				try {
+					TransformationUtils.executeRosTranformation(pkg, project, monitor);
+				} finally {
+					cmdActive = false;
 				}
-			};
-			job.setUser(true);
-			job.schedule();
-		}
+				return Status.OK_STATUS;
+			}
+		};
+		job.setUser(true);
+		job.schedule();
 		return null;
 	}
 
 	public static boolean isCmdActive() {
 		return cmdActive;
 	}
-	
+
 	public static boolean rewriteProject(String projectName) {
 		if (cmdActive) {
 			if (!rewriteMap.containsKey(projectName)) {
@@ -94,4 +88,4 @@
 		}
 		return false;
 	}
-} 
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/TransformationUtils.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/TransformationUtils.java
new file mode 100644
index 0000000..9b03b33
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/TransformationUtils.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2020 CEA LIST
+ * 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
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Ansgar Radermacher (CEA LIST) - initial API and implementation
+ *
+ *******************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.codegen.utils;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.emf.transaction.util.TransactionUtil;
+import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
+import org.eclipse.papyrus.designer.transformation.core.transformations.ExecuteTransformationChain;
+import org.eclipse.papyrus.designer.transformation.profile.Transformation.M2MTrafoChain;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+public class TransformationUtils {
+
+	public static final String ROS2_TRANSFORMATION_CHAIN = "ros2Library::m2mtransformations::ROSChain"; //$NON-NLS-1$
+
+	/**
+	 * Execute the ROS2 transformation chain on a given root package
+	 * @param pkg a root package (of a model)
+	 * @param project the current project
+	 * @param monitor a progress monitor
+	 */
+	public static void executeRosTranformation(Package pkg, IProject project, IProgressMonitor monitor) {
+		M2MTrafoChain transformation = TransformationUtils.getChain(pkg);
+
+		if (transformation != null) {
+
+			// execute the task ...
+			new ExecuteTransformationChain(pkg, project).executeTransformation(transformation, monitor, 0);
+		}
+	}
+
+	/**
+	 * Obtain the reference to the ROS2 transformation chain
+	 * 
+	 * @param element
+	 *            an arbitrary element (used to obtain resource set and editing domain)
+	 * @return the ROS2 transformation chain
+	 */
+	public static M2MTrafoChain getChain(Element element) {
+		TransactionalEditingDomain domain = TransactionUtil.getEditingDomain(element);
+
+		NamedElement rosChainCl = ElementUtils.getQualifiedElementFromRS(element, ROS2_TRANSFORMATION_CHAIN);
+		if (rosChainCl == null) {
+			PackageUtil.loadPackage(Helpers.ROS_LIBRARY_URI, domain.getResourceSet());
+			rosChainCl = ElementUtils.getQualifiedElementFromRS(element, ROS2_TRANSFORMATION_CHAIN);
+		}
+		if (rosChainCl != null) {
+			return UMLUtil.getStereotypeApplication(rosChainCl, M2MTrafoChain.class);
+		}
+		return null;
+	}
+}
diff --git a/releng/org.eclipse.papyrus.robotics.p2/pom.xml b/releng/org.eclipse.papyrus.robotics.p2/pom.xml
index 94a38ea..69d9565 100644
--- a/releng/org.eclipse.papyrus.robotics.p2/pom.xml
+++ b/releng/org.eclipse.papyrus.robotics.p2/pom.xml
@@ -48,9 +48,8 @@
 						
 						<!-- p2 update site transitive dependencies repositories -->
 							<associateSites>
-								<site>https://download.eclipse.org/modeling/mdt/papyrus/updates/releases/2019-12</site>
 								<!-- <site>https://download.eclipse.org/modeling/mdt/papyrus/components/designer/</site> -->
-								<site>https://hudson.eclipse.org/papyrus/job/papyrus-designer-2019-06/lastSuccessfulBuild/artifact/releng/org.eclipse.papyrus.designer.p2/target/repository/</site>
+								<site>https://hudson.eclipse.org/papyrus/job/papyrus-designer-2020-06/lastSuccessfulBuild/artifact/releng/org.eclipse.papyrus.designer.p2/target/repository/</site>
 								<site>https://download.eclipse.org/modeling/mdt/papyrus/components/marte/</site>
 								<site>https://download.eclipse.org/modeling/mdt/papyrus/components/sysml14/</site>
 								<site>https://ci.eclipse.org/esf/job/esf-infra-nightly-build/lastSuccessfulBuild/artifact/p2/target/repository/</site>