Bug 560665 - [Robotics, ROS2] Improve reverse mechanisms, support source code analysis

- Restructure, add code for source code analysis (remove this code from CDT editor to avoid duplication)
- However: source code analysis is incomplete and is currently not active. This will be done
  in a subsequent patch

Change-Id: I524f64a60e496b62dcbb8f89b3e85fdbf28ef267
Signed-off-by: Ansgar Radermacher <ansgar.radermacher@cea.fr>
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.core/src/org/eclipse/papyrus/robotics/core/utils/StringUtils.java b/plugins/customization/org.eclipse.papyrus.robotics.core/src/org/eclipse/papyrus/robotics/core/utils/StringUtils.java
deleted file mode 100644
index 8bb5ff5..0000000
--- a/plugins/customization/org.eclipse.papyrus.robotics.core/src/org/eclipse/papyrus/robotics/core/utils/StringUtils.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.eclipse.papyrus.robotics.core.utils;
-
-public class StringUtils {
-	public static String upperCaseFirst(String str) {
-		return str.substring(0, 1).toUpperCase() + str.substring(1);
-	}
-}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/PortInfo.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/PortInfo.java
deleted file mode 100644
index c89c403..0000000
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/PortInfo.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.eclipse.papyrus.robotics.ros2.cdteditor.sync;
-
-public class PortInfo {
-	
-	public enum ProviderKind {
-		PUBLISHER, SUBSCRIBER, CLIENT, SERVER, ACTION_CLI, ACTION_SRV
-	}
-	
-	public ProviderKind pk;
-	public String dtQName;
-	public String topic;
-}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncPortsFromSource.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncPortsFromSource.java
deleted file mode 100644
index 6bfadaa..0000000
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncPortsFromSource.java
+++ /dev/null
@@ -1,187 +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 v2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * Contributors:
- *  Ansgar Radermacher  ansgar.radermacher@cea.fr
- *
- *****************************************************************************/
-
-package org.eclipse.papyrus.robotics.ros2.cdteditor.sync;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
-import org.eclipse.cdt.core.dom.ast.IASTExpression;
-import org.eclipse.cdt.core.dom.ast.IASTExpressionList;
-import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
-import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
-import org.eclipse.cdt.core.dom.ast.IASTName;
-import org.eclipse.cdt.core.dom.ast.IASTNode;
-import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
-import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
-import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
-import org.eclipse.cdt.core.model.CoreModel;
-import org.eclipse.cdt.core.model.ITranslationUnit;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
-import org.eclipse.core.resources.ResourcesPlugin;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.papyrus.commands.Activator;
-import org.eclipse.papyrus.robotics.ros2.cdteditor.sync.PortInfo.ProviderKind;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.FileDialog;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.uml2.uml.Classifier;
-
-public class SyncPortsFromSource {
-
-	private static final String CREATE_PUBLISHER = "create_publisher"; //$NON-NLS-1$
-	private static final String CREATE_SUBSCRIPTION = "create_subscription"; //$NON-NLS-1$
-	private static final String CREATE_SERVICE = "create_service"; //$NON-NLS-1$
-	private static final String CREATE_CLIENT = "create_client"; //$NON-NLS-1$
-
-	private static final String EXTERNAL_FILES = "External Files"; //$NON-NLS-1$
-
-	public static void updatePorts(Classifier cl, IASTNode node) {
-		List<PortInfo> portInfoList = new ArrayList<PortInfo>();
-		scanFunctions(node, portInfoList);
-		for (PortInfo pi : portInfoList) {
-			System.err.println(pi.dtQName);
-			// NamedElement namedElemParamType = ElementUtils.getQualifiedElementFromRS(element, expr2);
-		}
-	}
-
-	public static void scanFunctions(IASTNode node, List<PortInfo> portInfoList) {
-
-		for (IASTNode child : node.getChildren()) {
-			if (child instanceof IASTFunctionDefinition) {
-				IASTFunctionDefinition definition = (IASTFunctionDefinition) child;
-				scanBody(definition.getBody(), portInfoList);
-			}
-			if (child instanceof ICPPASTNamespaceDefinition) {
-				// recurse into namespaces
-				scanFunctions(child, portInfoList);
-			}
-		}
-	}
-	public static String getASTName(IASTExpression expr) {
-		if (expr instanceof IASTFieldReference) {
-			IASTName fieldName = ((IASTFieldReference) expr).getFieldName();
-			if (fieldName != null) {
-				return fieldName.toString();
-			}
-			return ""; //$NON-NLS-1$
-		} else {
-			return expr.toString();
-		}
-	}
-
-	public static ProviderKind getProviderFromCall(String fctName) {
-		if (fctName.equals(CREATE_CLIENT)) {
-			return ProviderKind.CLIENT;
-		}
-		if (fctName.equals(CREATE_SERVICE)) {
-			return ProviderKind.SERVER;
-		}
-		if (fctName.equals(CREATE_SUBSCRIPTION)) {
-			return ProviderKind.SUBSCRIBER;
-		}
-		if (fctName.equals(CREATE_PUBLISHER)) {
-			return ProviderKind.PUBLISHER;
-		}
-		return null;
-	}
-
-	public static PortInfo obtainCallDetails(ProviderKind pk, IASTExpression expr1, IASTExpression expr2) {
-		IASTExpression expr2b = ((IASTBinaryExpression) expr1).getOperand2();
-		IASTExpression topicExpr = null;
-		if (expr2 instanceof IASTUnaryExpression) {
-			IASTExpression arguments = ((IASTUnaryExpression) expr2).getOperand();
-			if (arguments instanceof IASTExpressionList) {
-				topicExpr = ((IASTExpressionList) arguments).getExpressions()[0];
-			} else {
-				topicExpr = arguments;
-			}
-		}
-		String topicName = topicExpr.toString();
-		// remove quotes
-		if (topicName.startsWith("\"") && topicName.length()>=2) { //$NON-NLS-1$
-			topicName = topicName.substring(1, topicName.length()-1);
-		}
-		PortInfo portInfo = new PortInfo();
-		portInfo.pk = pk;
-		portInfo.dtQName = getASTName(expr2b);
-		portInfo.topic = topicName;
-		return portInfo;
-}
-	
-	public static void scanBody(IASTNode node, List<PortInfo> portList) {
-		if (node instanceof IASTBinaryExpression) {
-			IASTBinaryExpression expr = (IASTBinaryExpression) node;
-			IASTExpression expr1 = expr.getOperand1();
-			IASTExpression expr2 = expr.getOperand2();
-			if (expr1 instanceof IASTBinaryExpression) {
-				IASTExpression expr1b = ((IASTBinaryExpression) expr1).getOperand1();
-				String fieldName = getASTName(expr1b);
-
-				if (fieldName != null) {
-					ProviderKind pk = getProviderFromCall(fieldName);
-					if (pk != null) {
-						PortInfo portInfo = obtainCallDetails(pk, expr1, expr2);
-						if (portInfo != null) {
-							portList.add(portInfo);
-						}
-					}	
-				}
-			}
-		}
-		for (IASTNode child : node.getChildren()) {
-			// recurse into all children
-			scanBody(child, portList);
-		}
-	}
-
-	public static void tst() {
-		IWorkspace ws = ResourcesPlugin.getWorkspace();
-		IProject project = ws.getRoot().getProject(EXTERNAL_FILES);
-
-		try {
-			if (!project.exists())
-				project.create(null);
-			if (!project.isOpen())
-				project.open(null);
-			Shell shell = Display.getDefault().getActiveShell();
-			String name = (1 == 0) ? "/local/home/ansgar/prog/ros2/demos/demo_nodes_cpp/src/services/add_two_ints_client.cpp" : new FileDialog(shell, SWT.OPEN).open();
-			if (name == null)
-				return;
-			IPath location = new Path(name);
-			IFile srcFile = project.getFile(location.lastSegment());
-			boolean exists = srcFile.exists();
-			if (exists) {
-				srcFile.delete(false, null);
-			}
-			srcFile.createLink(location, IResource.NONE, null);
-
-
-			ITranslationUnit itu = (ITranslationUnit) CoreModel.getDefault().create(srcFile);
-
-			IASTTranslationUnit ast = itu.getAST();
-			scanFunctions(ast, new ArrayList<PortInfo>());
-
-		} catch (CoreException e) {
-			Activator.log.error(e);
-		}
-	}
-}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsCDTtoModel.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsCDTtoModel.java
index 703cd4d..e8125e4 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsCDTtoModel.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.cdteditor/src/org/eclipse/papyrus/robotics/ros2/cdteditor/sync/SyncRoboticsCDTtoModel.java
@@ -99,7 +99,7 @@
 
 				examineChildren(itu, selector, itu);
 				updateCppInclude(itu);
-				SyncPortsFromSource.updatePorts(m_classifier, ast);
+				// SyncPortsFromSource.updatePorts(m_classifier, ast);
 
 				CUIPlugin.getDefault().getProblemMarkerManager();
 				if (itu instanceof IWorkingCopy) {
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Activator.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Activator.java
index c48ae3d..a083262 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Activator.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Activator.java
@@ -1,6 +1,5 @@
 /*****************************************************************************
- * Copyright (c) 2013 CEA LIST.
- *
+ * 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 v2.0
@@ -11,6 +10,7 @@
  *  Ansgar Radermacher  ansgar.radermacher@cea.fr
  *
  *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse;
 
 import org.eclipse.papyrus.infra.core.log.LogHelper;
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ParamInfo.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ParamInfo.java
new file mode 100644
index 0000000..0711fcf
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ParamInfo.java
@@ -0,0 +1,23 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse;
+
+public class ParamInfo {
+	
+	public String name;
+	public String cppType;
+	public String defaultValue;
+	public String description;
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/PortInfo.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/PortInfo.java
new file mode 100644
index 0000000..28d2232
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/PortInfo.java
@@ -0,0 +1,26 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse;
+
+public class PortInfo {
+	
+	public enum ProviderKind {
+		PUBLISHER, SUBSCRIBER, CLIENT, SERVER, ACTION_CLI, ACTION_SRV
+	}
+	
+	public ProviderKind pk;
+	public String dtQName;
+	public String topic;
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseConstants.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseConstants.java
new file mode 100644
index 0000000..a7948c8
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseConstants.java
@@ -0,0 +1,20 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse;
+
+public class ReverseConstants {
+
+	public static final String MODEL_NAME_UC = "[modelNameUC]"; //$NON-NLS-1$
+
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseNodes.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseNodes.java
deleted file mode 100644
index 0c8ced6..0000000
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseNodes.java
+++ /dev/null
@@ -1,376 +0,0 @@
-package org.eclipse.papyrus.robotics.ros2.reverse;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.List;
-
-import org.eclipse.core.commands.ExecutionException;
-import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IFolder;
-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.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.transaction.RecordingCommand;
-import org.eclipse.emf.transaction.TransactionalEditingDomain;
-import org.eclipse.gmf.runtime.common.core.command.ICommand;
-import org.eclipse.gmf.runtime.notation.Diagram;
-import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
-import org.eclipse.papyrus.designer.languages.cpp.library.CppUriConstants;
-import org.eclipse.papyrus.infra.core.resource.BadArgumentExcetion;
-import org.eclipse.papyrus.infra.core.resource.ModelSet;
-import org.eclipse.papyrus.infra.core.resource.NotFoundException;
-import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry;
-import org.eclipse.papyrus.infra.core.services.ServiceException;
-import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
-import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
-import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationUtils;
-import org.eclipse.papyrus.robotics.core.utils.FileExtensions;
-import org.eclipse.papyrus.robotics.core.utils.ParameterUtils;
-import org.eclipse.papyrus.robotics.core.utils.PortUtils;
-import org.eclipse.papyrus.robotics.core.utils.ScanUtils;
-import org.eclipse.papyrus.robotics.core.utils.StringUtils;
-import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentPort;
-import org.eclipse.papyrus.robotics.ros2.reverse.MessageParser.MessageEntry;
-import org.eclipse.papyrus.robotics.ros2.reverse.utils.FolderUtils;
-import org.eclipse.papyrus.robotics.ros2.reverse.utils.ReverseUtils;
-import org.eclipse.papyrus.uml.diagram.wizards.Activator;
-import org.eclipse.papyrus.uml.diagram.wizards.command.InitFromTemplateCommand;
-import org.eclipse.papyrus.uml.diagram.wizards.command.NewPapyrusModelCommand;
-import org.eclipse.papyrus.uml.tools.model.UmlModel;
-import org.eclipse.papyrus.uml.tools.model.UmlUtils;
-import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
-import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
-import org.eclipse.uml2.uml.AggregationKind;
-import org.eclipse.uml2.uml.Class;
-import org.eclipse.uml2.uml.Interface;
-import org.eclipse.uml2.uml.NamedElement;
-import org.eclipse.uml2.uml.Package;
-import org.eclipse.uml2.uml.Port;
-import org.eclipse.uml2.uml.Property;
-import org.eclipse.uml2.uml.Type;
-
-@SuppressWarnings("nls")
-public class ReverseNodes {
-
-	private static final String MODEL_NAME_UC = "[modelNameUC]";
-
-	enum PortKind {
-		PUBSUB, SERVICE, ACTION
-	};
-
-	enum PortDirection {
-		PROVIDED, REQUIRED
-	};
-
-	public static void reverseNodes(IProgressMonitor monitor) {
-		ProcessBuilder pbMsg = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.NODE, Ros2Constants.LIST);
-		readNodeList(pbMsg, monitor);
-	}
-
-	/**
-	 * read the list of nodes and create models.
-	 * 
-	 * @param pb
-	 *            a process builder object with a suitable ROS2 command
-	 */
-	public static void readNodeList(ProcessBuilder pb, IProgressMonitor monitor) {
-		try {
-			Process p = pb.start();
-			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
-			StringBuffer errorMsg = new StringBuffer();
-			boolean error = ReverseUtils.logErrors(p, errorMsg);
-			if (error) {
-				Activator.log.debug(errorMsg.toString());
-				return;
-			}
-			String line;
-			List<URI> pathMapURIs = ScanUtils.allPathmapModels(FileExtensions.SERVICEDEF_UML);
-
-			while ((line = results.readLine()) != null) {
-				String frags[] = line.split(MessageParser.SLASH);
-				if (frags.length == 2) {
-					try {
-						String pkgName = frags[0].trim();
-						String name = frags[1].trim();
-						// ignore some nodes
-						if (name.endsWith("_rclcpp_node") || name.endsWith("_client_node") ||
-								name.startsWith("transform_listener_") || name.startsWith("launch_ros_")) {
-							continue;
-						}
-
-						monitor.subTask("reverse component " + name);
-						String fileName = name + FileExtensions.COMPDEF_UML;
-						// pass complete filename (a bit abusing the extension attribute)
-						IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
-						if (pkgName.length() == 0) {
-							pkgName = name;
-						}
-						IProject project = root.getProject(pkgName);
-						IProgressMonitor progressMonitor = new NullProgressMonitor();
-						if (!project.exists()) {
-							project.create(progressMonitor);
-						}
-						if (!project.isOpen()) {
-							project.open(progressMonitor);
-						}
-
-						IFolder fModels = FolderUtils.createFolderStructure(project);
-						IFolder fComponents = FolderUtils.getComponentFolder(fModels);
-						IFile fCompModel = fComponents.getFile(fileName);
-						if (!fCompModel.exists()) {
-
-							ServicesRegistry registry = new ExtensionServicesRegistry(org.eclipse.papyrus.infra.core.Activator.PLUGIN_ID);
-							registry.startServicesByClassKeys(ModelSet.class);
-
-							ModelSet modelSet = registry.getService(ModelSet.class);
-							TransactionalEditingDomain domain = modelSet.getTransactionalEditingDomain();
-
-							URI newURIs = URI.createURI("platform:/resource/" + pkgName + "/models/components/" + fileName);
-							RecordingCommand command = new NewPapyrusModelCommand(modelSet, newURIs);
-							domain.getCommandStack().execute(command);
-
-							InitFromTemplateCommand tp = new InitFromTemplateCommand(modelSet.getTransactionalEditingDomain(), modelSet,
-									"org.eclipse.papyrus.robotics.wizards",
-									"templates/robotics.compdef.uml", "templates/robotics.compdef.notation", "templates/robotics.compdef.di");
-							domain.getCommandStack().execute(tp);
-
-							UmlModel umlModel = UmlUtils.getUmlModel(modelSet);
-							final NotationModel notation = NotationUtils.getNotationModel(modelSet);
-
-							final Package pkg = (Package) umlModel.lookupRoot();
-							// load primitive types
-							PackageUtil.loadPackage(URI.createURI(ReverseMessages.PATHMAP_ROS2_PRIMITIVE_UML), pkg.eResource().getResourceSet());
-							PackageUtil.loadPackage(CppUriConstants.ANSIC_LIB, pkg.eResource().getResourceSet());
-
-							final String lineFinal = line;
-							RecordingCommand reverseComponent = new RecordingCommand(domain) {
-								@Override
-								protected void doExecute() {
-									pkg.setName(name);
-									ReverseUtils.setXmlID(pkg);
-
-									Class clazz = (Class) pkg.getOwnedType(MODEL_NAME_UC);
-									clazz.setName(name);
-									ReverseUtils.setXmlID(clazz);
-									reversePorts(clazz, lineFinal, pathMapURIs);
-									reverseParams(clazz, lineFinal, pathMapURIs);
-
-									Diagram diagram;
-									try {
-										diagram = notation.getDiagram(MODEL_NAME_UC);
-										final String newName = StringUtils.upperCaseFirst(name) + " diagram";
-										diagram.setName(newName);
-									} catch (NotFoundException | BadArgumentExcetion e) {
-										e.printStackTrace();
-									}
-								}
-							};
-							domain.getCommandStack().execute(reverseComponent);
-
-							modelSet.save(progressMonitor);
-							registry.disposeRegistry();
-						} else {
-							// TODO: in the moment, we do not touch existing projects
-						}
-					} catch (CoreException | ServiceException | NotFoundException e) {
-						e.printStackTrace();
-					}
-					monitor.worked(1);
-					if (monitor.isCanceled())
-						break;
-				}
-			}
-			results.close();
-		} catch (IOException exp) {
-			Activator.log.error(exp);
-		}
-	}
-
-	public static void reversePorts(Class component, String qName, List<URI> pathMapURIs) {
-		ProcessBuilder pb = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.NODE, Ros2Constants.INFO, qName);
-		try {
-			Process p = pb.start();
-			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
-			StringBuffer errorMsg = new StringBuffer();
-			boolean error = ReverseUtils.logErrors(p, errorMsg);
-			if (error) {
-				Activator.log.debug(errorMsg.toString());
-				return;
-			}
-			String line;
-			PortKind current = PortKind.PUBSUB;
-			PortDirection direction = PortDirection.PROVIDED;
-			while ((line = results.readLine()) != null) {
-				line = MessageParser.filterComment(line);
-				if (line.contains("Publishers:")) {
-					current = PortKind.PUBSUB;
-					direction = PortDirection.PROVIDED;
-				} else if (line.contains("Subscribers:")) {
-					current = PortKind.PUBSUB;
-					direction = PortDirection.REQUIRED;
-				} else if (line.contains("Service servers:")) {
-					current = PortKind.SERVICE;
-					direction = PortDirection.PROVIDED;
-				} else if (line.contains("Service clients:")) {
-					current = PortKind.SERVICE;
-					direction = PortDirection.REQUIRED;
-				} else if (line.contains("Action servers:")) {
-					current = PortKind.ACTION;
-					direction = PortDirection.PROVIDED;
-				} else if (line.contains("Action clients:")) {
-					current = PortKind.ACTION;
-					direction = PortDirection.REQUIRED;
-				} else {
-					String frags[] = line.split(MessageParser.COLON);
-					if (frags.length == 2) {
-						String qPortName = frags[0].trim();
-						String qMessageName = frags[1].trim();
-						MessageEntry entry = MessageParser.extractMessageEntry(qMessageName);
-						if (entry.pkgName.equals("rcl_interfaces") || entry.pkgName.equals("lifecycle")) {
-							// length 3, e.g. "/ROSadder/change_state: lifecycle_msgs/srv/ChangeState" indicate automatically
-							// standard interfaces
-							// TODO - might need info whether a lifecycle node.
-							continue;
-						}
-						if (entry.name.equals("clock")) {
-							continue;
-						}
-						Interface sd = getServiceDef(component, current, entry);
-						if (sd == null) {
-							// check, if the model representing the ROS2 resource is already in the resource set
-							if (ElementUtils.getQualifiedElementFromRS(component, entry.pkgName) == null) {
-								// not loaded => load and retry to get service definition
-								String fileName = ReverseUtils.fileName(entry.pkgName);
-								// load message set from registered packages (TODO: important restriction?)
-								// Cannot use the load function in ReverseUtils, since this loads into the "wrong" resource set
-								for (URI pathURI : pathMapURIs) {
-									if (pathURI.toString().endsWith(fileName)) {
-										component.eResource().getResourceSet().getResource(pathURI, true);
-										sd = getServiceDef(component, current, entry);
-										break;
-									}
-								}
-							}
-							if (sd == null) {
-								Activator.log.debug(String.format("Cannot find service definition for %s", qMessageName));
-								break;
-							}
-						}
-						String portName = qPortName.trim().substring(1);
-						Port port = component.createOwnedPort(portName, null);
-						ReverseUtils.setXmlID(port);
-						port.setAggregation(AggregationKind.COMPOSITE_LITERAL);
-						StereotypeUtil.apply(port, ComponentPort.class);
-						ICommand csCmd = PortUtils.associateCSCommand(port);
-						csCmd.execute(null, null);
-						Class cs = (Class) port.getType();
-						if (direction == PortDirection.PROVIDED) {
-							cs.createInterfaceRealization(null, sd);
-						} else {
-							cs.createUsage(sd);
-						}
-					}
-				}
-			}
-			results.close();
-
-		} catch (IOException exp) {
-			Activator.log.error(exp);
-		} catch (ExecutionException exp) {
-			Activator.log.error(exp);
-		}
-	}
-
-	public static void reverseParams(Class component, String qName, List<URI> pathMapURIs) {
-		ProcessBuilder pb = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.PARAM, Ros2Constants.LIST, qName);
-		try {
-			Process p = pb.start();
-			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
-			StringBuffer errorMsg = new StringBuffer();
-			boolean error = ReverseUtils.logErrors(p, errorMsg);
-			if (error) {
-				Activator.log.debug(errorMsg.toString());
-				return;
-			}
-			String line;
-			// read list of ROS parameters and add these to the list of parameters of the
-			// describe command
-			ProcessBuilder pbDesc = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.PARAM, Ros2Constants.DESCRIBE, qName);
-			while (results.ready() && (line = results.readLine()) != null) {
-				String param = line.trim();
-				pbDesc.command().add(param);
-			}
-			results.close();
-
-			String paramName = "";
-			Class paramSet = ParameterUtils.getParameterClass(component);
-			// now obtain type
-			Process pDesc = pbDesc.start();
-			results = new BufferedReader(new InputStreamReader(pDesc.getInputStream()));
-			error = ReverseUtils.logErrors(pDesc, errorMsg);
-			if (error) {
-				Activator.log.debug(errorMsg.toString());
-			}
-			while (results.ready() && (line = results.readLine()) != null) {
-				String desc = line.trim();
-				if (desc.startsWith("Parameter name:")) {
-					paramName = desc.substring("Parameter name:".length()).trim();
-				}
-				if (desc.startsWith("Type:")) {
-					String type = desc.substring(5).trim();
-					int upper = 1;
-					if (type.equals("string array")) {	// TODO - right mapping?
-						type = "string";
-						upper = -1;
-					}
-					String name = "primitive" + NamedElement.SEPARATOR + type;
-					NamedElement ne = ElementUtils.getQualifiedElementFromRS(component, name);
-					if (ne == null) {
-						if (type.equals("boolean")) {
-							type = "bool";
-						}
-						if (type.equals("integer")) {
-							type = "int";
-						}
-						name = "AnsiCLibrary" + NamedElement.SEPARATOR + type;
-						ne = ElementUtils.getQualifiedElementFromRS(component, name);
-					}
-					Property paramUML = paramSet.createOwnedAttribute(paramName, (Type) ne);
-					if (upper != 1) {
-						paramUML.setUpper(upper);
-					}
-					if (ne == null) {
-						Activator.log.debug(String.format("Cannot find type %s", type));
-					}
-				}
-			}
-			results.close();
-
-		} catch (IOException exp) {
-			Activator.log.error(exp);
-		}
-	}
-
-	public static Interface getServiceDef(Class component, PortKind portKind, MessageEntry entry) {
-		String prefix = "";
-		if (portKind == PortKind.PUBSUB) {
-			prefix = "P_";
-		} else if (portKind == PortKind.SERVICE) {
-			prefix = "Q_";
-		} else if (portKind == PortKind.ACTION) {
-			prefix = "A_";
-		}
-		String qName = entry.pkgName + NamedElement.SEPARATOR + Ros2Constants.SVCDEFS + NamedElement.SEPARATOR
-				+ prefix + entry.name;
-		NamedElement ne = ElementUtils.getQualifiedElementFromRS(component, qName);
-		if (ne instanceof Interface) {
-			return (Interface) ne;
-		}
-		return null;
-	}
-}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Ros2Constants.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Ros2Constants.java
index 4286860..7069b18 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Ros2Constants.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/Ros2Constants.java
@@ -1,3 +1,16 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse;
 
 @SuppressWarnings("nls")
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodeFromSource.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodeFromSource.java
new file mode 100644
index 0000000..848ef63
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodeFromSource.java
@@ -0,0 +1,181 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromfile;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.papyrus.designer.languages.common.base.StringUtils;
+import org.eclipse.papyrus.designer.languages.cpp.library.CppUriConstants;
+import org.eclipse.papyrus.infra.core.resource.BadArgumentExcetion;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
+import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
+import org.eclipse.papyrus.robotics.core.utils.FileExtensions;
+import org.eclipse.papyrus.robotics.ros2.reverse.Activator;
+import org.eclipse.papyrus.robotics.ros2.reverse.ReverseConstants;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.ReverseMessages;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.FolderUtils;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.ModelTemplate;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.ReverseUtils;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Package;
+
+public class ReverseNodeFromSource {
+
+	private static final String PACKAGE_XML = "package.xml"; //$NON-NLS-1$
+	private static final String NAME_TAG = "<name>"; //$NON-NLS-1$
+	private static final String NAME_TAG_END = "</name>"; //$NON-NLS-1$
+
+	public static void reverseNode(IFile file, IProgressMonitor monitor) {
+		try {
+			String pkgName = null;
+			IFile packageXML = scanPackageXML(file.getParent());
+			if (packageXML != null) {
+				BufferedReader results = new BufferedReader(new InputStreamReader(packageXML.getContents()));
+				String line;
+				while ((line = results.readLine()) != null) {
+					line = line.trim();
+					if (line.startsWith(NAME_TAG)) {
+						pkgName = line.substring(NAME_TAG.length());
+						int idx = pkgName.indexOf(NAME_TAG_END);
+						if (idx != -1) {
+							pkgName = pkgName.substring(0, idx);
+						}
+						break;
+					}
+				}
+			}
+			// TODO - obtain nodeName from code
+			String name = file.getName();
+			if (name.endsWith(".cpp")) {
+				name = name.substring(0, name.length() - 4);
+			}
+
+			monitor.beginTask("reverse component " + name, 3);
+			monitor.subTask("obtain AST");
+			ITranslationUnit itu = (ITranslationUnit) CoreModel.getDefault().create(file);
+			IASTTranslationUnit ast = itu.getAST();
+			monitor.worked(1);
+
+			String fileName = name + FileExtensions.COMPDEF_UML;
+			// pass complete filename (a bit abusing the extension attribute)
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			if (pkgName == null) {
+				IProject project = FolderUtils.obtainProject(fileName);
+				if (project != null) {
+					pkgName = project.getName();
+				} else {
+					pkgName = name;
+				}
+			}
+
+			IProject project = root.getProject(pkgName);
+			IProgressMonitor progressMonitor = new NullProgressMonitor();
+			if (!project.exists()) {
+				project.create(progressMonitor);
+			}
+			if (!project.isOpen()) {
+				project.open(progressMonitor);
+			}
+
+			IFolder fModels = FolderUtils.createFolderStructure(project);
+			IFolder fComponents = FolderUtils.getComponentFolder(fModels);
+			IFile fCompModel = fComponents.getFile(fileName);
+
+			if (!fCompModel.exists()) {
+				URI newURI = URI.createURI("platform:/resource/" + pkgName + "/models/components/" + fileName);
+				ModelTemplate mt = new ModelTemplate(newURI, "compdef");
+				final NotationModel notation = mt.getNotationModel();
+
+				final Package pkg = mt.getUMLModel();
+				// load primitive types
+				PackageUtil.loadPackage(URI.createURI(ReverseMessages.PATHMAP_ROS2_PRIMITIVE_UML), pkg.eResource().getResourceSet());
+				PackageUtil.loadPackage(CppUriConstants.ANSIC_LIB, pkg.eResource().getResourceSet());
+
+				final String nameFinal = name;
+				final String pkgNameFinal = pkgName;
+				RecordingCommand reverseComponent = new RecordingCommand(mt.getDomain()) {
+					@Override
+					protected void doExecute() {
+						pkg.setName(pkgNameFinal);
+						ReverseUtils.setXmlID(pkg);
+
+						Class clazz = (Class) pkg.getOwnedType(ReverseConstants.MODEL_NAME_UC);
+						clazz.setName(nameFinal);
+						ReverseUtils.setXmlID(clazz);
+
+						Diagram diagram;
+						try {
+							diagram = notation.getDiagram(ReverseConstants.MODEL_NAME_UC);
+							final String newName = StringUtils.upperCaseFirst(nameFinal) + " diagram";
+							diagram.setName(newName);
+						} catch (NotFoundException | BadArgumentExcetion e) {
+							e.printStackTrace();
+						}
+
+						monitor.subTask("obtain ports");
+						ReversePortsFromSource.updatePorts(clazz, ast);
+						monitor.worked(1);
+
+						monitor.subTask("obtain parameters");
+						ReverseParametersFromSource.updateParameters(clazz, ast);
+						monitor.worked(1);
+					}
+				};
+				mt.executeCmd(reverseComponent);
+				
+				mt.save(monitor);
+			}
+		} catch (Exception e) {
+			Activator.log.error(e);
+		}
+	}
+
+	/**
+	 * Scan folder for package.xml file
+	 * 
+	 * @param folder
+	 *            a folder where the seach is started
+	 * @return
+	 */
+	public static IFile scanPackageXML(IContainer folder) {
+		IFile candidate = folder.getFile(new Path(PACKAGE_XML));
+		if (candidate != null && candidate.exists()) {
+			return candidate;
+		}
+		if (folder.getParent() != null) {
+			IFile result = scanPackageXML(folder.getParent());
+			if (result != null) {
+				return result;
+			}
+		}
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseParametersFromSource.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseParametersFromSource.java
new file mode 100644
index 0000000..94e05d9
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseParametersFromSource.java
@@ -0,0 +1,170 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromfile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
+import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
+import org.eclipse.papyrus.designer.languages.common.base.StringUtils;
+import org.eclipse.papyrus.robotics.ros2.reverse.ParamInfo;
+import org.eclipse.uml2.uml.Class;
+
+public class ReverseParametersFromSource {
+
+	private static final String ADD_PARAMETER = "add_parameter"; //$NON-NLS-1$
+	private static final String GET_PARAMETER = "get_parameter"; //$NON-NLS-1$
+	private static final String DECLARE_PARAMETER = "declare_parameter"; //$NON-NLS-1$
+
+	enum EParam {
+		ADD_OR_DECLARE,
+		GET_PARAM,
+		NONE
+	};
+	
+	public static void updateParameters(Class clazz, IASTNode node) {
+		List<ParamInfo> paramInfoList = new ArrayList<ParamInfo>();
+		scanFunctions(node, paramInfoList);
+		for (ParamInfo pi : paramInfoList) {
+			System.err.println(pi.name);
+			// NamedElement namedElemParamType = ElementUtils.getQualifiedElementFromRS(element, expr2);
+		}
+	}
+
+	public static void scanFunctions(IASTNode node, List<ParamInfo> paramInfoList) {
+
+		for (IASTNode child : node.getChildren()) {
+			if (child instanceof IASTFunctionDefinition) {
+				IASTFunctionDefinition definition = (IASTFunctionDefinition) child;
+				scanBody(definition.getBody(), paramInfoList);
+			}
+			if (child instanceof ICPPASTNamespaceDefinition) {
+				// recurse into namespaces
+				scanFunctions(child, paramInfoList);
+			}
+		}
+	}
+
+	public static String getASTName(IASTExpression expr) {
+		if (expr instanceof IASTFieldReference) {
+			IASTName fieldName = ((IASTFieldReference) expr).getFieldName();
+			if (fieldName != null) {
+				return fieldName.toString();
+			}
+			return ""; //$NON-NLS-1$
+		} else {
+			return expr.toString();
+		}
+	}
+
+	public static EParam getProviderFromCall(String fctName) {
+		if (fctName.equals(DECLARE_PARAMETER)) {
+			return EParam.ADD_OR_DECLARE;
+		}
+		if (fctName.equals(ADD_PARAMETER)) {
+			return EParam.ADD_OR_DECLARE;
+		}
+		if (fctName.equals(GET_PARAMETER)) {
+			return EParam.GET_PARAM;
+		}
+		return EParam.NONE;
+	}
+
+	/**
+	 * Obtain default value from declare or add_parameter call
+	 * @param fCallExpr
+	 */
+	public static void obtainDeclOrAddDetails(IASTFunctionCallExpression fCallExpr) {
+		IASTInitializerClause arguments[] = fCallExpr.getArguments();
+		String parameterName = arguments[0].toString();
+		parameterName = StringUtils.unquote(parameterName);
+		String defaultValue = null;
+		String description = null;
+		if (arguments.length > 1) {
+			if (arguments[1] instanceof IASTFunctionCallExpression) {
+				IASTInitializerClause argument = arguments[1];
+				while (argument instanceof IASTFunctionCallExpression) {
+					arguments = ((IASTFunctionCallExpression) arguments[1]).getArguments();
+					if (arguments.length == 1) {
+						
+					}
+				}
+				defaultValue = ((IASTFunctionCallExpression) arguments[1]).getArguments()[0].toString();
+			}
+			// String parameterName = fCallExpr.getArguments()[0].toString();
+
+			if (arguments.length > 2) {
+				description = arguments[2].toString();
+			}
+		}
+		System.err.println("param: " + parameterName); //$NON-NLS-1$
+		if (defaultValue != null) System.err.println("  " + defaultValue);
+		if (description != null) System.err.println("  " + description);
+	}
+
+	/**
+	 * The type can be obtained from the get_parameter call
+	 * @param fCallExpr
+	 */
+	public static void obtainGetDetails(IASTFunctionCallExpression fCallExpr) {
+		IASTInitializerClause arguments[] = fCallExpr.getArguments();
+		String parameterName = arguments[0].toString();
+		parameterName = StringUtils.unquote(parameterName);
+		String type = null;
+		if (arguments.length > 1) {
+			if (arguments[1] instanceof IASTIdExpression) {
+				IASTIdExpression id = (IASTIdExpression) arguments[1];
+				ASTNodeProperty x = id.getPropertyInParent();
+				System.err.println(x);
+				// type = 
+			}
+		}
+		if (type != null) {
+			// System.err.println("  " + defaultValue);
+		}
+	}
+
+	public static void scanBody(IASTNode node, List<ParamInfo> paramList) {
+		if (node instanceof IASTFunctionCallExpression) {
+			IASTFunctionCallExpression fCallExpr = (IASTFunctionCallExpression) node;
+			IASTExpression nameExpr = fCallExpr.getFunctionNameExpression();
+			if (nameExpr instanceof IASTIdExpression) {
+				IASTIdExpression nameId = (IASTIdExpression) nameExpr;
+				IASTName astName = nameId.getName();
+				String fctName = astName.toString();
+				EParam param = getProviderFromCall(fctName);
+				if (param == EParam.ADD_OR_DECLARE) {
+					obtainDeclOrAddDetails(fCallExpr);
+				}
+				else if (param == EParam.GET_PARAM) {
+					obtainGetDetails(fCallExpr);
+				}
+			}
+		}
+		for (IASTNode child : node.getChildren()) {
+			// recurse into all children
+			scanBody(child, paramList);
+		}
+	}
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReversePortsFromSource.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReversePortsFromSource.java
new file mode 100644
index 0000000..21c4286
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReversePortsFromSource.java
@@ -0,0 +1,142 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromfile;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.dom.ast.IASTExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
+import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
+import org.eclipse.cdt.core.dom.ast.IASTName;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
+import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo;
+import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo.ProviderKind;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Port;
+
+public class ReversePortsFromSource {
+
+	private static final String CREATE_PUBLISHER = "create_publisher"; //$NON-NLS-1$
+	private static final String CREATE_SUBSCRIPTION = "create_subscription"; //$NON-NLS-1$
+	private static final String CREATE_SERVICE = "create_service"; //$NON-NLS-1$
+	private static final String CREATE_CLIENT = "create_client"; //$NON-NLS-1$
+	private static final String CREATE_ACTION_SRV = "rclcpp_action::create_server"; //$NON-NLS-1$
+	private static final String CREATE_ACTION_CLI = "rclcpp_action::create_client"; //$NON-NLS-1$
+
+	public static void updatePorts(Class clazz, IASTNode node) {
+		List<PortInfo> portInfoList = new ArrayList<PortInfo>();
+		scanFunctions(node, portInfoList);
+		
+		for (PortInfo pi : portInfoList) {
+			Port port = clazz.createOwnedPort(pi.dtQName, null);
+			System.err.println(pi.dtQName);
+		}
+	}
+
+	public static void scanFunctions(IASTNode node, List<PortInfo> portInfoList) {
+
+		for (IASTNode child : node.getChildren()) {
+			if (child instanceof IASTFunctionDefinition) {
+				IASTFunctionDefinition definition = (IASTFunctionDefinition) child;
+				scanBody(definition.getBody(), portInfoList);
+			}
+			if (child instanceof ICPPASTNamespaceDefinition) {
+				// recurse into namespaces
+				scanFunctions(child, portInfoList);
+			}
+		}
+	}
+	public static String getASTName(IASTExpression expr) {
+		if (expr instanceof IASTFieldReference) {
+			IASTName fieldName = ((IASTFieldReference) expr).getFieldName();
+			if (fieldName != null) {
+				return fieldName.toString();
+			}
+			return ""; //$NON-NLS-1$
+		} else {
+			return expr.toString();
+		}
+	}
+
+	public static ProviderKind getProviderFromCall(String fctName) {
+		if (fctName.equals(CREATE_CLIENT)) {
+			return ProviderKind.CLIENT;
+		}
+		else if (fctName.equals(CREATE_SERVICE)) {
+			return ProviderKind.SERVER;
+		}
+		else if (fctName.equals(CREATE_SUBSCRIPTION)) {
+			return ProviderKind.SUBSCRIBER;
+		}
+		else if (fctName.equals(CREATE_PUBLISHER)) {
+			return ProviderKind.PUBLISHER;
+		}
+		else if (fctName.equals(CREATE_ACTION_SRV)) {
+			return ProviderKind.ACTION_SRV;
+		}
+		else if (fctName.equals(CREATE_ACTION_CLI)) {
+			return ProviderKind.ACTION_CLI;
+		}
+		return null;
+	}
+
+	/**
+	 * This function obtains the PortInfo from AST data
+	 * @param pk
+	 * @param fCallExpr the function call expression
+	 * @param templateId the template-id
+	 */
+	public static PortInfo obtainCallDetails(ProviderKind pk, IASTFunctionCallExpression fCallExpr, ICPPASTTemplateId templateId) {
+		String topicName = fCallExpr.getArguments()[0].toString();
+		PortInfo portInfo = new PortInfo();
+		portInfo.pk = pk;
+		portInfo.dtQName = templateId.getTemplateArguments()[0].toString();
+		portInfo.topic = topicName;
+		return portInfo;
+	}
+	
+	public static void scanBody(IASTNode node, List<PortInfo> portList) {
+		if (node instanceof IASTFunctionCallExpression) {
+			IASTFunctionCallExpression fCallExpr = (IASTFunctionCallExpression) node;
+			IASTExpression nameExpr = fCallExpr.getFunctionNameExpression();
+			if (nameExpr instanceof IASTIdExpression) {
+				IASTIdExpression nameId = (IASTIdExpression) nameExpr;
+				IASTName astName = nameId.getName();
+				if (astName instanceof ICPPASTTemplateId) {
+					// all ROS2 "ports" are created by binding one or more concrete message types
+					// e.g. create_publisher<geometry_msgs::msg::PoseArray>(...)
+					ICPPASTTemplateId templateId = (ICPPASTTemplateId) astName;
+					String fctName = templateId.getTemplateName().toString();
+					ProviderKind pk = getProviderFromCall(fctName);
+					if (pk != null) {
+						PortInfo portInfo = obtainCallDetails(pk, fCallExpr, templateId);
+						if (portInfo != null) {
+							portList.add(portInfo);
+						}
+					}	
+				}
+			}
+		}
+		for (IASTNode child : node.getChildren()) {
+			// recurse into all children
+			scanBody(child, portList);
+		}
+	}
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/MessageParser.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/MessageParser.java
similarity index 83%
rename from plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/MessageParser.java
rename to plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/MessageParser.java
index 314db2f..cfcec21 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/MessageParser.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/MessageParser.java
@@ -1,8 +1,23 @@
-package org.eclipse.papyrus.robotics.ros2.reverse;
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromsys;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.papyrus.robotics.ros2.reverse.Activator;
 import org.eclipse.uml2.uml.DataType;
 
 public class MessageParser {
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/NodeInfo.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/NodeInfo.java
new file mode 100644
index 0000000..313be63
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/NodeInfo.java
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromsys;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo;
+import org.eclipse.uml2.uml.Class;
+
+public class NodeInfo {
+	String name;
+	Class type;
+	List<PortInfo> ports = new ArrayList<PortInfo>();
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseMessages.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseMessages.java
similarity index 94%
rename from plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseMessages.java
rename to plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseMessages.java
index f68ad16..83df4e9 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/ReverseMessages.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseMessages.java
@@ -1,4 +1,17 @@
-package org.eclipse.papyrus.robotics.ros2.reverse;
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.fromsys;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -22,8 +35,10 @@
 import org.eclipse.papyrus.robotics.library.advice.QueryCommPatternAdvice;
 import org.eclipse.papyrus.robotics.library.advice.SendCommPatternAdvice;
 import org.eclipse.papyrus.robotics.profile.robotics.services.ServiceDefinition;
-import org.eclipse.papyrus.robotics.ros2.reverse.MessageParser.MessageEntry;
-import org.eclipse.papyrus.robotics.ros2.reverse.MessageParser.NameType;
+import org.eclipse.papyrus.robotics.ros2.reverse.Activator;
+import org.eclipse.papyrus.robotics.ros2.reverse.Ros2Constants;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.MessageParser.MessageEntry;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.MessageParser.NameType;
 import org.eclipse.papyrus.robotics.ros2.reverse.utils.ReverseUtils;
 import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
 import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseNodes.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseNodes.java
new file mode 100644
index 0000000..7b71444
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromsys/ReverseNodes.java
@@ -0,0 +1,493 @@
+package org.eclipse.papyrus.robotics.ros2.reverse.fromsys;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+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.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.gmf.runtime.common.core.command.ICommand;
+import org.eclipse.gmf.runtime.notation.Diagram;
+import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
+import org.eclipse.papyrus.designer.languages.common.base.StringUtils;
+import org.eclipse.papyrus.designer.languages.cpp.library.CppUriConstants;
+import org.eclipse.papyrus.designer.transformation.base.utils.ModelManagement;
+import org.eclipse.papyrus.infra.core.resource.BadArgumentExcetion;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
+import org.eclipse.papyrus.robotics.core.utils.FileExtensions;
+import org.eclipse.papyrus.robotics.core.utils.InteractionUtils;
+import org.eclipse.papyrus.robotics.core.utils.ParameterUtils;
+import org.eclipse.papyrus.robotics.core.utils.PortUtils;
+import org.eclipse.papyrus.robotics.core.utils.ScanUtils;
+import org.eclipse.papyrus.robotics.profile.robotics.commpattern.CommunicationPattern;
+import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentPort;
+import org.eclipse.papyrus.robotics.profile.robotics.parameters.ParameterEntry;
+import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo;
+import org.eclipse.papyrus.robotics.ros2.reverse.PortInfo.ProviderKind;
+import org.eclipse.papyrus.robotics.ros2.reverse.ReverseConstants;
+import org.eclipse.papyrus.robotics.ros2.reverse.Ros2Constants;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.MessageParser.MessageEntry;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.FolderUtils;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.ModelTemplate;
+import org.eclipse.papyrus.robotics.ros2.reverse.utils.ReverseUtils;
+import org.eclipse.papyrus.uml.diagram.wizards.Activator;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
+import org.eclipse.uml2.uml.AggregationKind;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Connector;
+import org.eclipse.uml2.uml.ConnectorEnd;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.Port;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.Type;
+
+@SuppressWarnings("nls")
+public class ReverseNodes {
+
+	enum PortKind {
+		PUBSUB, SERVICE, ACTION
+	};
+
+	enum PortDirection {
+		PROVIDED, REQUIRED
+	};
+
+	protected IProgressMonitor monitor;
+
+	protected List<URI> pathMapURIs;
+
+	protected List<NodeInfo> niList;
+
+	protected Map<String, List<NodeInfo>> portHash;
+
+	public static void reverseNodes(IProgressMonitor monitor) {
+		new ReverseNodes(monitor).readNodeList();
+	}
+
+	public ReverseNodes(IProgressMonitor monitor) {
+		this.monitor = monitor;
+		pathMapURIs = ScanUtils.allPathmapModels(FileExtensions.SERVICEDEF_UML);
+		niList = new ArrayList<NodeInfo>();
+		portHash = new HashMap<String, List<NodeInfo>>();
+	}
+
+	/**
+	 * read the list of nodes and create models.
+	 */
+	public void readNodeList() {
+		ProcessBuilder pb = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.NODE, Ros2Constants.LIST);
+		try {
+			Process p = pb.start();
+			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
+			StringBuffer errorMsg = new StringBuffer();
+			boolean error = ReverseUtils.logErrors(p, errorMsg);
+			if (error) {
+				Activator.log.debug(errorMsg.toString());
+				return;
+			}
+
+			// first, read all lines into an array in order to calculate
+			// the number of nodes
+			String line1;
+			List<String> lines = new ArrayList<String>();
+			while ((line1 = results.readLine()) != null) {
+				String frags[] = line1.split(MessageParser.SLASH);
+				if (frags.length == 2) {
+					String name = frags[1].trim();
+					if (name.endsWith("_rclcpp_node") || name.endsWith("_client_node") ||
+							name.startsWith("transform_listener_") || name.startsWith("launch_ros_")) {
+						// skip
+					} else {
+						lines.add(line1);
+					}
+				}
+			}
+			results.close();
+
+			monitor.beginTask("reverse nodes", lines.size() + 1);
+			for (String line : lines) {
+				reverseNode(line);
+				monitor.worked(1);
+				if (monitor.isCanceled())
+					break;
+			}
+			createSystem();
+		} catch (IOException exp) {
+			Activator.log.error(exp);
+		}
+	}
+
+	public void reverseNode(String line) {
+		String frags[] = line.split(MessageParser.SLASH);
+		try {
+			String pkgName = frags[0].trim();
+			String name = frags[1].trim();
+			// ignore some nodes
+
+			monitor.subTask("reverse component " + name);
+			String fileName = name + FileExtensions.COMPDEF_UML;
+			// pass complete filename (a bit abusing the extension attribute)
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			if (pkgName.length() == 0) {
+				IProject project = FolderUtils.obtainProject(fileName);
+				if (project != null) {
+					pkgName = project.getName();
+				}
+				else {
+					// could not determine
+					pkgName = name;
+				}
+			}
+
+			IProject project = root.getProject(pkgName);
+			IProgressMonitor progressMonitor = new NullProgressMonitor();
+			if (!project.exists()) {
+				project.create(progressMonitor);
+			}
+			if (!project.isOpen()) {
+				project.open(progressMonitor);
+			}
+
+			NodeInfo ni = new NodeInfo();
+			ni.name = name;
+			IFolder fModels = FolderUtils.createFolderStructure(project);
+			IFolder fComponents = FolderUtils.getComponentFolder(fModels);
+			IFile fCompModel = fComponents.getFile(fileName);
+			URI newURI = URI.createURI("platform:/resource/" + pkgName + "/models/components/" + fileName);
+			if (!fCompModel.exists()) {
+				ModelTemplate mt = new ModelTemplate(newURI, "compdef");
+				final NotationModel notation = mt.getNotationModel();
+
+				final Package pkg = mt.getUMLModel();
+				// load primitive types
+				PackageUtil.loadPackage(URI.createURI(ReverseMessages.PATHMAP_ROS2_PRIMITIVE_UML), pkg.eResource().getResourceSet());
+				PackageUtil.loadPackage(CppUriConstants.ANSIC_LIB, pkg.eResource().getResourceSet());
+
+				final String lineFinal = line;
+				RecordingCommand reverseComponent = new RecordingCommand(mt.getDomain()) {
+					@Override
+					protected void doExecute() {
+						pkg.setName(name);
+						ReverseUtils.setXmlID(pkg);
+
+						Class clazz = (Class) pkg.getOwnedType(ReverseConstants.MODEL_NAME_UC);
+						ni.type = clazz;
+						clazz.setName(name);
+						ReverseUtils.setXmlID(clazz);
+						reversePorts(clazz, ni, lineFinal);
+						reverseParams(clazz, lineFinal);
+
+						Diagram diagram;
+						try {
+							diagram = notation.getDiagram(ReverseConstants.MODEL_NAME_UC);
+							final String newName = StringUtils.upperCaseFirst(name) + " diagram";
+							diagram.setName(newName);
+						} catch (NotFoundException | BadArgumentExcetion e) {
+							e.printStackTrace();
+						}
+					}
+				};
+				mt.executeCmd(reverseComponent);
+				mt.save(progressMonitor);
+				mt.dispose();
+			} else {
+				// obtain clazz
+				ModelManagement.getResourceSet().getResource(newURI, true);
+				String qualifiedName = "*::" + name;
+				NamedElement ne = ElementUtils.getQualifiedElementFromRS(ModelManagement.getResourceSet(), qualifiedName);
+				if (ne instanceof Class) {
+					ni.type = (Class) ne;
+				} else {
+					Activator.log.debug("not found");
+				}
+				// reverse ports without updating the component (in order to fill port hashMap)
+				reversePorts(null, ni, line);
+				// TODO: in the moment, we do not touch existing projects
+			}
+			niList.add(ni);
+		} catch (CoreException | ServiceException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public void createSystem() {
+		String fileName = "fromRos.uml";
+		URI newURI = URI.createURI("platform:/resource/reverse/models/system/" + fileName);
+		Resource r = ModelManagement.getResourceSet().getResource(newURI, true);
+		if (r != null) {
+			// model already exists, don't overwrite it.
+			return;
+		}
+		try {
+			ModelTemplate mt = new ModelTemplate(newURI, "system");
+			RecordingCommand rc = new RecordingCommand(mt.getDomain()) {
+
+				@Override
+				protected void doExecute() {
+					Package root = mt.getUMLModel();
+					Diagram diagram;
+					try {
+						diagram = mt.getNotationModel().getDiagram(ReverseConstants.MODEL_NAME_UC);
+						diagram.setName("System diagram");
+					} catch (NotFoundException | BadArgumentExcetion e) {
+						Activator.log.error(e);
+						;
+					}
+					Class system = (Class) root.getOwnedMember("System");
+					for (NodeInfo ni : niList) {
+						system.createOwnedAttribute(ni.name, ni.type);
+					}
+					for (String portName : portHash.keySet()) {
+						Connector c = system.createOwnedConnector(null);
+						for (NodeInfo ni : portHash.get(portName)) {
+							ConnectorEnd end = c.createEnd();
+
+							end.setPartWithPort(system.getAttribute(ni.name, null));
+							end.setRole(ni.type.getOwnedPort(portName, null));
+						}
+						if (c.getEnds().size() < 2) {
+							c.destroy();
+						}
+					}
+				}
+			};
+			mt.executeCmd(rc);
+			mt.save(monitor);
+		} catch (ServiceException e) {
+			Activator.log.error(e);
+			;
+		}
+
+	}
+
+	public void reversePorts(Class component, NodeInfo ni, String qName) {
+		ProcessBuilder pb = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.NODE, Ros2Constants.INFO, qName);
+		try {
+			Process p = pb.start();
+			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
+			StringBuffer errorMsg = new StringBuffer();
+			boolean error = ReverseUtils.logErrors(p, errorMsg);
+			if (error) {
+				Activator.log.debug(errorMsg.toString());
+				return;
+			}
+			String line;
+			PortKind current = PortKind.PUBSUB;
+			PortDirection direction = PortDirection.PROVIDED;
+			while ((line = results.readLine()) != null) {
+				line = MessageParser.filterComment(line);
+				if (line.contains("Publishers:")) {
+					current = PortKind.PUBSUB;
+					direction = PortDirection.PROVIDED;
+				} else if (line.contains("Subscribers:")) {
+					current = PortKind.PUBSUB;
+					direction = PortDirection.REQUIRED;
+				} else if (line.contains("Service Servers:")) {
+					current = PortKind.SERVICE;
+					direction = PortDirection.PROVIDED;
+				} else if (line.contains("Service Clients:")) {
+					current = PortKind.SERVICE;
+					direction = PortDirection.REQUIRED;
+				} else if (line.contains("Action Servers:")) {
+					current = PortKind.ACTION;
+					direction = PortDirection.PROVIDED;
+				} else if (line.contains("Action Clients:")) {
+					current = PortKind.ACTION;
+					direction = PortDirection.REQUIRED;
+				} else {
+					String frags[] = line.split(MessageParser.COLON);
+					if (frags.length == 2) {
+						String qPortName = frags[0].trim();
+						String qMessageName = frags[1].trim();
+						MessageEntry entry = MessageParser.extractMessageEntry(qMessageName);
+						if (entry.pkgName.equals("rcl_interfaces")
+								|| entry.pkgName.equals("lifecycle_msgs")
+								|| entry.pkgName.equals("rosgraph_msgs")) {
+							// length 3, e.g. "/ROSadder/change_state: lifecycle_msgs/srv/ChangeState" indicate automatically
+							// standard interfaces
+							// TODO - might need info whether a lifecycle node.
+							continue;
+						}
+						String portName = qPortName.trim().substring(1);
+						List<NodeInfo> niWithName = portHash.get(portName);
+						if (niWithName == null) {
+							niWithName = new ArrayList<NodeInfo>();
+						}
+						niWithName.add(ni);
+						portHash.put(portName, niWithName);
+						if (component == null) {
+							continue;
+						}
+						Interface sd = getServiceDef(component, current, entry);
+						if (sd == null) {
+							// check, if the model representing the ROS2 resource is already in the resource set
+							if (ElementUtils.getQualifiedElementFromRS(component, entry.pkgName) == null) {
+								// not loaded => load and retry to get service definition
+								String fileName = ReverseUtils.fileName(entry.pkgName);
+								// load message set from registered packages (TODO: important restriction?)
+								// Cannot use the load function in ReverseUtils, since this loads into the "wrong" resource set
+								for (URI pathURI : pathMapURIs) {
+									if (pathURI.toString().endsWith(fileName)) {
+										component.eResource().getResourceSet().getResource(pathURI, true);
+										sd = getServiceDef(component, current, entry);
+										break;
+									}
+								}
+							}
+							if (sd == null) {
+								Activator.log.debug(String.format("Cannot find service definition for %s", qMessageName));
+								break;
+							}
+						}
+						PortInfo pi = new PortInfo();
+						ni.ports.add(pi);
+						pi.dtQName = portName;
+						Port port = component.createOwnedPort(portName, null);
+						ReverseUtils.setXmlID(port);
+						port.setAggregation(AggregationKind.COMPOSITE_LITERAL);
+						StereotypeUtil.apply(port, ComponentPort.class);
+						ICommand csCmd = PortUtils.associateCSCommand(port);
+						csCmd.execute(null, null);
+						Class cs = (Class) port.getType();
+						TemplateBinding tb = InteractionUtils.getTemplateBinding(sd);
+						CommunicationPattern cp = InteractionUtils.getCommunicationPattern(tb);
+						if (direction == PortDirection.PROVIDED) {
+							cs.createInterfaceRealization(null, sd);
+							if (InteractionUtils.isPush(cp)) {
+								pi.pk = ProviderKind.PUBLISHER;
+							} else if (InteractionUtils.isQuery(cp)) {
+								pi.pk = ProviderKind.SERVER;
+							} else if (InteractionUtils.isAction(cp)) {
+								pi.pk = ProviderKind.ACTION_SRV;
+							}
+						} else {
+							cs.createUsage(sd);
+							if (InteractionUtils.isPush(cp)) {
+								pi.pk = ProviderKind.SUBSCRIBER;
+							} else if (InteractionUtils.isQuery(cp)) {
+								pi.pk = ProviderKind.CLIENT;
+							} else if (InteractionUtils.isAction(cp)) {
+								pi.pk = ProviderKind.ACTION_CLI;
+							}
+						}
+					}
+				}
+			}
+			results.close();
+
+		} catch (IOException exp) {
+			Activator.log.error(exp);
+		} catch (ExecutionException exp) {
+			Activator.log.error(exp);
+		}
+	}
+
+	public void reverseParams(Class component, String qName) {
+		ProcessBuilder pb = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.PARAM, Ros2Constants.LIST, qName);
+		try {
+			Process p = pb.start();
+			BufferedReader results = new BufferedReader(new InputStreamReader(p.getInputStream()));
+			StringBuffer errorMsg = new StringBuffer();
+			boolean error = ReverseUtils.logErrors(p, errorMsg);
+			if (error) {
+				Activator.log.debug(errorMsg.toString());
+				return;
+			}
+			String line;
+			// read list of ROS parameters and add these to the list of parameters of the
+			// describe command
+			ProcessBuilder pbDesc = new ProcessBuilder(Ros2Constants.ROS2, Ros2Constants.PARAM, Ros2Constants.DESCRIBE, qName);
+			while (results.ready() && (line = results.readLine()) != null) {
+				String param = line.trim();
+				pbDesc.command().add(param);
+			}
+			results.close();
+
+			String paramName = "";
+			Class paramSet = ParameterUtils.getParameterClass(component);
+			// now obtain type
+			Process pDesc = pbDesc.start();
+			results = new BufferedReader(new InputStreamReader(pDesc.getInputStream()));
+			error = ReverseUtils.logErrors(pDesc, errorMsg);
+			if (error) {
+				Activator.log.debug(errorMsg.toString());
+			}
+			while (results.ready() && (line = results.readLine()) != null) {
+				String desc = line.trim();
+				if (desc.startsWith("Parameter name:")) {
+					paramName = desc.substring("Parameter name:".length()).trim();
+				}
+				if (desc.startsWith("Type:")) {
+					String type = desc.substring(5).trim();
+					int upper = 1;
+					if (type.equals("string array")) { // TODO - right mapping?
+						type = "string";
+						upper = -1;
+					}
+					String name = "primitive" + NamedElement.SEPARATOR + type;
+					NamedElement ne = ElementUtils.getQualifiedElementFromRS(component, name);
+					if (ne == null) {
+						if (type.equals("boolean")) {
+							type = "bool";
+						}
+						if (type.equals("integer")) {
+							type = "int";
+						}
+						name = "AnsiCLibrary" + NamedElement.SEPARATOR + type;
+						ne = ElementUtils.getQualifiedElementFromRS(component, name);
+					}
+					Property paramUML = paramSet.createOwnedAttribute(paramName, (Type) ne);
+					StereotypeUtil.apply(paramUML, ParameterEntry.class);
+					if (upper != 1) {
+						paramUML.setUpper(upper);
+					}
+					if (ne == null) {
+						Activator.log.debug(String.format("Cannot find type %s", type));
+					}
+				}
+			}
+			results.close();
+
+		} catch (IOException exp) {
+			Activator.log.error(exp);
+		}
+	}
+
+	public static Interface getServiceDef(Class component, PortKind portKind, MessageEntry entry) {
+		String prefix = "";
+		if (portKind == PortKind.PUBSUB) {
+			prefix = "P_";
+		} else if (portKind == PortKind.SERVICE) {
+			prefix = "Q_";
+		} else if (portKind == PortKind.ACTION) {
+			prefix = "A_";
+		}
+		String qName = entry.pkgName + NamedElement.SEPARATOR + Ros2Constants.SVCDEFS + NamedElement.SEPARATOR
+				+ prefix + entry.name;
+		NamedElement ne = ElementUtils.getQualifiedElementFromRS(component, qName);
+		if (ne instanceof Interface) {
+			return (Interface) ne;
+		}
+		return null;
+	}
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseMessagesHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseMessagesHandler.java
index cc16b6d..f9122d4 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseMessagesHandler.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseMessagesHandler.java
@@ -1,3 +1,17 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse.handlers;
 
 import org.eclipse.core.commands.AbstractHandler;
@@ -9,7 +23,7 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.papyrus.robotics.ros2.reverse.ReverseMessages;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.ReverseMessages;
 import org.eclipse.ui.PlatformUI;
 
 public class ReverseMessagesHandler extends AbstractHandler {
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodeFromFileHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodeFromFileHandler.java
new file mode 100644
index 0000000..92f2d75
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodeFromFileHandler.java
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.robotics.ros2.reverse.handlers;
+
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromfile.ReverseNodeFromSource;
+import org.eclipse.ui.PlatformUI;
+
+public class ReverseNodeFromFileHandler extends AbstractHandler {
+
+	protected IFile file;
+
+	@Override
+	public boolean isEnabled() {
+		// Retrieve selected elements
+		IStructuredSelection selection = (IStructuredSelection) PlatformUI
+				.getWorkbench().getActiveWorkbenchWindow()
+				.getSelectionService().getSelection();
+
+		if (selection.getFirstElement() instanceof IFile) {
+			file = (IFile) selection.getFirstElement();
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public Object execute(ExecutionEvent arg0) throws ExecutionException {
+		Job job = new Job("Reverse ROS messages and services") { //$NON-NLS-1$
+			@Override
+			protected IStatus run(final IProgressMonitor monitor) {
+				ReverseNodeFromSource.reverseNode(file, monitor);
+				return Status.OK_STATUS;
+			}
+		};
+		job.schedule();
+
+		return null;
+	}
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesHandler.java
index dda6005..9f282f8 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesHandler.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesHandler.java
@@ -1,3 +1,17 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse.handlers;
 
 import org.eclipse.core.commands.AbstractHandler;
@@ -7,7 +21,7 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.papyrus.robotics.ros2.reverse.ReverseNodes;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromsys.ReverseNodes;
 
 public class ReverseNodesHandler extends AbstractHandler {
 
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/FolderUtils.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/FolderUtils.java
index 887db11..777969c 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/FolderUtils.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/FolderUtils.java
@@ -1,9 +1,27 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse.utils;
 
 import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 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.Path;
 import org.eclipse.papyrus.robotics.ros2.reverse.Activator;
 
@@ -36,4 +54,26 @@
 		return getOrCreate(fModels, COMPONENTS);
 
 	}
+	
+	/**
+	 * Obtain an existing project (and thus the presumed package) based on
+	 * the assumption that the filename of the component definition corresponds
+	 * to the node name that is published.
+	 * 
+	 * @param fileName
+	 *            the filename of a component definition
+	 * @return the obtained project name or null, if none found
+	 */
+	public static IProject obtainProject(String fileName) {
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		for (IProject project : root.getProjects()) {
+			IPath path = new Path("/models/components/" + fileName);
+			IFile file = project.getFile(path);
+			if (file.exists()) {
+				return project;
+			}
+		}
+		return null;
+	}
+
 }
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ModelTemplate.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ModelTemplate.java
new file mode 100644
index 0000000..1dfe783
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ModelTemplate.java
@@ -0,0 +1,80 @@
+package org.eclipse.papyrus.robotics.ros2.reverse.utils;
+
+import java.io.IOException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.transaction.RecordingCommand;
+import org.eclipse.emf.transaction.TransactionalEditingDomain;
+import org.eclipse.papyrus.commands.Activator;
+import org.eclipse.papyrus.infra.core.resource.ModelSet;
+import org.eclipse.papyrus.infra.core.resource.NotFoundException;
+import org.eclipse.papyrus.infra.core.services.ExtensionServicesRegistry;
+import org.eclipse.papyrus.infra.core.services.ServiceException;
+import org.eclipse.papyrus.infra.core.services.ServiceMultiException;
+import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
+import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
+import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationUtils;
+import org.eclipse.papyrus.uml.diagram.wizards.command.InitFromTemplateCommand;
+import org.eclipse.papyrus.uml.diagram.wizards.command.NewPapyrusModelCommand;
+import org.eclipse.papyrus.uml.tools.model.UmlModel;
+import org.eclipse.papyrus.uml.tools.model.UmlUtils;
+import org.eclipse.uml2.uml.Package;
+
+public class ModelTemplate {
+	ServicesRegistry registry;
+
+	ModelSet modelSet;
+
+	public ModelTemplate(URI uri, String extension) throws ServiceException {
+		registry = new ExtensionServicesRegistry(org.eclipse.papyrus.infra.core.Activator.PLUGIN_ID);
+		registry.startServicesByClassKeys(ModelSet.class);
+
+		modelSet = registry.getService(ModelSet.class);
+		TransactionalEditingDomain domain = modelSet.getTransactionalEditingDomain();
+
+		RecordingCommand command = new NewPapyrusModelCommand(modelSet, uri);
+		domain.getCommandStack().execute(command);
+
+		String templateName = "templates/robotics." + extension;
+		InitFromTemplateCommand tp = new InitFromTemplateCommand(modelSet.getTransactionalEditingDomain(), modelSet,
+				"org.eclipse.papyrus.robotics.wizards",
+				templateName + ".uml", templateName + ".notation", templateName + ".di");
+		domain.getCommandStack().execute(tp);
+	}
+
+	public Package getUMLModel() {
+		UmlModel umlModel = UmlUtils.getUmlModel(modelSet);
+		try {
+			return (Package) umlModel.lookupRoot();
+		} catch (NotFoundException e) {
+			Activator.log.error(e);
+		}
+		return null;
+	}
+
+	public void save(IProgressMonitor progressMonitor) {
+		try {
+			modelSet.save(progressMonitor);
+		} catch (IOException e) {
+			Activator.log.error(e);
+		}
+	}
+
+	public TransactionalEditingDomain getDomain() {
+		return modelSet.getTransactionalEditingDomain();
+	}
+
+	public void executeCmd(Command command) {
+		getDomain().getCommandStack().execute(command);
+	}
+
+	public NotationModel getNotationModel() {
+		return NotationUtils.getNotationModel(modelSet);
+	}
+
+	public void dispose() throws ServiceMultiException {
+		registry.disposeRegistry();
+	}
+}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ReverseUtils.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ReverseUtils.java
index c62380f..405e102 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ReverseUtils.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/utils/ReverseUtils.java
@@ -1,3 +1,17 @@
+/*****************************************************************************
+ * 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 v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * Contributors:
+ *  Ansgar Radermacher  ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
 package org.eclipse.papyrus.robotics.ros2.reverse.utils;
 
 import java.io.BufferedReader;