Bug 568313 - [Robotics, ROS2] Create library of existing components and enable their use in system assembly

Bug 568313 - [Robotics, ROS2] Create library of existing components and enable their use in system assembly

- Add an "external" flag to the component definition model stereotype

- Take flag into account by not generating code and calculating the ROS2 package name differently: since it is possible to host external components belonging to different ROS2 packages in the same Eclipse project, the ROS2 package is calculated from the model name and not from the containing project.

- In order to obtain external libraries more easily, a new reverse option that automatically scans a ROS2 workspace and extracts component information from all classes that inherit from "Node" or "LifecycleNode". This option proposes to setup the CDT project

Change-Id: Ic7c662fc696b94c18b762164f9daa99e4c1e408c
Signed-off-by: Ansgar Radermacher <ansgar.radermacher@cea.fr>
diff --git a/plugins/codegen/org.eclipse.papyrus.robotics.codegen.common/src/org/eclipse/papyrus/robotics/codegen/common/utils/PackageTools.xtend b/plugins/codegen/org.eclipse.papyrus.robotics.codegen.common/src/org/eclipse/papyrus/robotics/codegen/common/utils/PackageTools.xtend
index fdd7d2a..3ec6ceb 100644
--- a/plugins/codegen/org.eclipse.papyrus.robotics.codegen.common/src/org/eclipse/papyrus/robotics/codegen/common/utils/PackageTools.xtend
+++ b/plugins/codegen/org.eclipse.papyrus.robotics.codegen.common/src/org/eclipse/papyrus/robotics/codegen/common/utils/PackageTools.xtend
@@ -28,6 +28,8 @@
 import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil
 import org.eclipse.uml2.uml.Class
 import org.eclipse.uml2.uml.Package
+import org.eclipse.uml2.uml.util.UMLUtil
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil
 
 class PackageTools {
 
@@ -38,10 +40,19 @@
 	 * @return The ROS2 package name
 	 */
 	def static String pkgName(Package model) {
+		if (model === null) {
+			System.err.println("Haeh");
+		}
 		if (StereotypeUtil.isApplied(model, ServiceDefinitionModel)) {
 			return model.name.toLowerCase
 		}
 		else {
+			// in case of an external components, use model name in order to enable multiple
+			// packages in a single Eclipse project
+			val compDefModel = UMLUtil.getStereotypeApplication(model, ComponentDefinitionModel)
+			if (compDefModel !== null && compDefModel.isExternal) {
+				return model.name.toLowerCase
+			}
 			return model.projectName.toLowerCase
 		}
 	}
@@ -114,7 +125,11 @@
 			val srcCompRes = srcRS.getResource(compDefURI, true)
 			val compDef = findOrCopyCompDef(srcCompRes);
 			if (compDef !== null) {
-				compDefs.add(compDef)
+				val root = PackageUtil.getRootPackage(compDef);
+				val cdm = UMLUtil.getStereotypeApplication(root, ComponentDefinitionModel)
+				if (cdm !== null && !cdm.isExternal) {
+					compDefs.add(compDef)
+				}
 			}
 		}
 		return compDefs
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.ecore b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.ecore
index 367799b..30ee9cd 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.ecore
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.ecore
@@ -103,6 +103,10 @@
           upperBound="-1" eType="ecore:EDataType platform:/plugin/org.eclipse.uml2.types/model/Types.ecore#//String"/>
       <eStructuralFeatures xsi:type="ecore:EAttribute" name="registered" ordered="false"
           eType="ecore:EDataType platform:/plugin/org.eclipse.uml2.types/model/Types.ecore#//Boolean"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="external" ordered="false"
+          eType="ecore:EDataType platform:/plugin/org.eclipse.uml2.types/model/Types.ecore#//Boolean"/>
+      <eStructuralFeatures xsi:type="ecore:EAttribute" name="license" ordered="false"
+          eType="ecore:EDataType platform:/plugin/org.eclipse.uml2.types/model/Types.ecore#//String"/>
     </eClassifiers>
     <eClassifiers xsi:type="ecore:EClass" name="SystemComponentArchitectureModel"
         eSuperTypes="platform:/plugin/org.eclipse.papyrus.robotics.bpc.profile/model/bpc.ecore#//Entity">
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.genmodel b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.genmodel
index 2b7d9b6..c69a756 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.genmodel
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.genmodel
@@ -108,6 +108,8 @@
             propertySortChoices="true" ecoreFeature="ecore:EReference robotics.ecore#//components/ComponentDefinitionModel/base_Package"/>
         <genFeatures xsi:type="genmodel:GenFeature" createChild="false" ecoreFeature="ecore:EAttribute robotics.ecore#//components/ComponentDefinitionModel/dependsPackage"/>
         <genFeatures xsi:type="genmodel:GenFeature" createChild="false" ecoreFeature="ecore:EAttribute robotics.ecore#//components/ComponentDefinitionModel/registered"/>
+        <genFeatures xsi:type="genmodel:GenFeature" createChild="false" ecoreFeature="ecore:EAttribute robotics.ecore#//components/ComponentDefinitionModel/external"/>
+        <genFeatures xsi:type="genmodel:GenFeature" createChild="false" ecoreFeature="ecore:EAttribute robotics.ecore#//components/ComponentDefinitionModel/license"/>
       </genClasses>
       <genClasses xsi:type="genmodel:GenClass" ecoreClass="robotics.ecore#//components/SystemComponentArchitectureModel">
         <genFeatures xsi:type="genmodel:GenFeature" notify="false" createChild="false"
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.notation b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.notation
index 4b3998e..57c5279 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.notation
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.notation
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:css="http://www.eclipse.org/papyrus/infra/gmfdiag/css" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.2/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/gmfdiag/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
+<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:css="http://www.eclipse.org/papyrus/infra/gmfdiag/css" xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" xmlns:notation="http://www.eclipse.org/gmf/runtime/1.0.3/notation" xmlns:style="http://www.eclipse.org/papyrus/infra/gmfdiag/style" xmlns:uml="http://www.eclipse.org/uml2/5.0.0/UML">
   <notation:Diagram xmi:id="_CvGQAJZ2Eeeq1f8hGgKVzA" type="PapyrusUMLProfileDiagram" name="overview" measurementUnit="Pixel">
     <children xmi:type="notation:Shape" xmi:id="_Bdtb8Je7EeeiCOWsEr9OuA" type="Profile_Shape">
       <children xmi:type="notation:DecorationNode" xmi:id="_Bdv4MJe7EeeiCOWsEr9OuA" type="Profile_NameLabel"/>
@@ -1079,7 +1079,7 @@
         <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9wvtrJ0uEeeBys1xGPG1Rg"/>
       </children>
       <element xmi:type="uml:Stereotype" href="robotics.profile.uml#_9wtRYJ0uEeeBys1xGPG1Rg"/>
-      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9wvtoZ0uEeeBys1xGPG1Rg" x="394" y="480" width="221" height="78"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_9wvtoZ0uEeeBys1xGPG1Rg" x="394" y="500" width="221" height="78"/>
     </children>
     <children xmi:type="notation:Shape" xmi:id="_vQnEQPR-EeeeOeGeZwxiZw" type="Class_MetaclassShape" fillColor="14538691">
       <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_pAIDYBSYEei-CMVLY1Smdg" source="PapyrusCSSForceValue">
@@ -1149,7 +1149,7 @@
         <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fRtVShNDEei-CMVLY1Smdg"/>
       </children>
       <element xmi:type="uml:Stereotype" href="robotics.profile.uml#_f-vFQBNBEei-CMVLY1Smdg"/>
-      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fRsuMRNDEei-CMVLY1Smdg" x="60" y="480" width="141" height="78"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fRsuMRNDEei-CMVLY1Smdg" x="60" y="500" width="141" height="78"/>
     </children>
     <children xmi:type="notation:Shape" xmi:id="_N1qO8Df_EeirkoCxAcpuEA" type="Stereotype_Shape">
       <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_QehuoDf_EeirkoCxAcpuEA" source="PapyrusCSSForceValue">
@@ -1579,6 +1579,46 @@
       <element xsi:nil="true"/>
       <layoutConstraint xmi:type="notation:Bounds" xmi:id="_CuL4cvqGEeq_-ehCLre8sQ" x="980" y="400"/>
     </children>
+    <children xmi:type="notation:Shape" xmi:id="_fVzZUCQsEeuD8eTvhiVIwg" type="StereotypeComment">
+      <styles xmi:type="notation:TitleStyle" xmi:id="_fVzZUSQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fVzZUyQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Class"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fVzZUiQsEeuD8eTvhiVIwg" x="160" y="20"/>
+    </children>
+    <children xmi:type="notation:Shape" xmi:id="_fV9KUyQsEeuD8eTvhiVIwg" type="StereotypeComment">
+      <styles xmi:type="notation:TitleStyle" xmi:id="_fV9KVCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fV9KViQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#InstanceSpecification"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fV9KVSQsEeuD8eTvhiVIwg" x="594" y="400"/>
+    </children>
+    <children xmi:type="notation:Shape" xmi:id="_fWG7UyQsEeuD8eTvhiVIwg" type="StereotypeComment">
+      <styles xmi:type="notation:TitleStyle" xmi:id="_fWG7VCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWG7ViQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Port"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fWG7VSQsEeuD8eTvhiVIwg" x="720" y="20"/>
+    </children>
+    <children xmi:type="notation:Shape" xmi:id="_fWQsUyQsEeuD8eTvhiVIwg" type="StereotypeComment">
+      <styles xmi:type="notation:TitleStyle" xmi:id="_fWQsVCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWQsViQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Property"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fWQsVSQsEeuD8eTvhiVIwg" x="260" y="400"/>
+    </children>
+    <children xmi:type="notation:Shape" xmi:id="_fWfV0CQsEeuD8eTvhiVIwg" type="StereotypeComment">
+      <styles xmi:type="notation:TitleStyle" xmi:id="_fWfV0SQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWfV0yQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Package"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <layoutConstraint xmi:type="notation:Bounds" xmi:id="_fWfV0iQsEeuD8eTvhiVIwg" x="980" y="400"/>
+    </children>
     <styles xmi:type="notation:StringValueStyle" xmi:id="_ggTNUZbWEeeM7-EkGcZisw" name="diagram_compatibility_version" stringValue="1.4.0"/>
     <styles xmi:type="notation:DiagramStyle" xmi:id="_ggTNUpbWEeeM7-EkGcZisw"/>
     <styles xmi:type="style:PapyrusDiagramStyle" xmi:id="_ggTNU5bWEeeM7-EkGcZisw" diagramKindId="org.eclipse.papyrus.uml.diagram.profile">
@@ -1622,9 +1662,9 @@
     <edges xmi:type="notation:Connector" xmi:id="__WY1wJ0uEeeBys1xGPG1Rg" type="Extension_Edge" source="_9wvtoJ0uEeeBys1xGPG1Rg" target="_7TJCwJ0uEeeBys1xGPG1Rg" routing="Rectilinear">
       <styles xmi:type="notation:FontStyle" xmi:id="__WY1wZ0uEeeBys1xGPG1Rg"/>
       <element xmi:type="uml:Extension" href="robotics.profile.uml#__VOYIJ0uEeeBys1xGPG1Rg"/>
-      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="__WY1wp0uEeeBys1xGPG1Rg" points="[474, 480, -643984, -643984]$[474, 452, -643984, -643984]"/>
-      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="__WyeYJ0uEeeBys1xGPG1Rg" id="(0.36199095022624433,0.0)"/>
-      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="__WyeYZ0uEeeBys1xGPG1Rg" id="(0.26578073089701,1.0)"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="__WY1wp0uEeeBys1xGPG1Rg" points="[480, 480, -643984, -643984]$[480, 468, -643984, -643984]$[480, 455, -643984, -643984]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="__WyeYJ0uEeeBys1xGPG1Rg" id="(0.3891402714932127,0.0)"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="__WyeYZ0uEeeBys1xGPG1Rg" id="(0.2857142857142857,1.0)"/>
     </edges>
     <edges xmi:type="notation:Connector" xmi:id="_vQ9plPR-EeeeOeGeZwxiZw" type="StereotypeCommentLink" source="_vQnEQPR-EeeeOeGeZwxiZw">
       <styles xmi:type="notation:FontStyle" xmi:id="_vQ9plfR-EeeeOeGeZwxiZw"/>
@@ -1663,9 +1703,9 @@
     <edges xmi:type="notation:Connector" xmi:id="_iWsJMBNDEei-CMVLY1Smdg" type="Extension_Edge" source="_fRsuMBNDEei-CMVLY1Smdg" target="_aPTLUBNDEei-CMVLY1Smdg" routing="Rectilinear">
       <styles xmi:type="notation:FontStyle" xmi:id="_iWsJMRNDEei-CMVLY1Smdg"/>
       <element xmi:type="uml:Extension" href="robotics.profile.uml#_iWZ1UBNDEei-CMVLY1Smdg"/>
-      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_iWsJMhNDEei-CMVLY1Smdg" points="[134, 480, -643984, -643984]$[134, 452, -643984, -643984]"/>
-      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iW_rMBNDEei-CMVLY1Smdg" id="(0.524822695035461,0.0)"/>
-      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iW_rMRNDEei-CMVLY1Smdg" id="(0.24584717607973422,1.0)"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_iWsJMhNDEei-CMVLY1Smdg" points="[140, 480, -643984, -643984]$[140, 468, -643984, -643984]$[140, 455, -643984, -643984]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iW_rMBNDEei-CMVLY1Smdg" id="(0.5673758865248227,0.0)"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_iW_rMRNDEei-CMVLY1Smdg" id="(0.26578073089701,1.0)"/>
     </edges>
     <edges xmi:type="notation:Connector" xmi:id="_XBkk4Df_EeirkoCxAcpuEA" type="Extension_Edge" source="_N1qO8Df_EeirkoCxAcpuEA" target="_aPTLUBNDEei-CMVLY1Smdg">
       <styles xmi:type="notation:FontStyle" xmi:id="_XBkk4Tf_EeirkoCxAcpuEA"/>
@@ -2047,6 +2087,56 @@
       <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_CuL4d_qGEeq_-ehCLre8sQ"/>
       <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_CuL4ePqGEeq_-ehCLre8sQ"/>
     </edges>
+    <edges xmi:type="notation:Connector" xmi:id="_fVzZVCQsEeuD8eTvhiVIwg" type="StereotypeCommentLink" source="_l4mHsJbWEeeM7-EkGcZisw" target="_fVzZUCQsEeuD8eTvhiVIwg">
+      <styles xmi:type="notation:FontStyle" xmi:id="_fVzZVSQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fVzZWSQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Class"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fVzZViQsEeuD8eTvhiVIwg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fVzZVyQsEeuD8eTvhiVIwg"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fVzZWCQsEeuD8eTvhiVIwg"/>
+    </edges>
+    <edges xmi:type="notation:Connector" xmi:id="_fV9KVyQsEeuD8eTvhiVIwg" type="StereotypeCommentLink" source="_7TJCwJ0uEeeBys1xGPG1Rg" target="_fV9KUyQsEeuD8eTvhiVIwg">
+      <styles xmi:type="notation:FontStyle" xmi:id="_fV9KWCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fV9KXCQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#InstanceSpecification"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fV9KWSQsEeuD8eTvhiVIwg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fV9KWiQsEeuD8eTvhiVIwg"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fV9KWyQsEeuD8eTvhiVIwg"/>
+    </edges>
+    <edges xmi:type="notation:Connector" xmi:id="_fWG7VyQsEeuD8eTvhiVIwg" type="StereotypeCommentLink" source="_vQnEQPR-EeeeOeGeZwxiZw" target="_fWG7UyQsEeuD8eTvhiVIwg">
+      <styles xmi:type="notation:FontStyle" xmi:id="_fWG7WCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWG7XCQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Port"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fWG7WSQsEeuD8eTvhiVIwg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWG7WiQsEeuD8eTvhiVIwg"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWG7WyQsEeuD8eTvhiVIwg"/>
+    </edges>
+    <edges xmi:type="notation:Connector" xmi:id="_fWQsVyQsEeuD8eTvhiVIwg" type="StereotypeCommentLink" source="_aPTLUBNDEei-CMVLY1Smdg" target="_fWQsUyQsEeuD8eTvhiVIwg">
+      <styles xmi:type="notation:FontStyle" xmi:id="_fWQsWCQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWRTYCQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Property"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fWQsWSQsEeuD8eTvhiVIwg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWQsWiQsEeuD8eTvhiVIwg"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWQsWyQsEeuD8eTvhiVIwg"/>
+    </edges>
+    <edges xmi:type="notation:Connector" xmi:id="_fWfV1CQsEeuD8eTvhiVIwg" type="StereotypeCommentLink" source="_twkUcElaEeicede5K86kPg" target="_fWfV0CQsEeuD8eTvhiVIwg">
+      <styles xmi:type="notation:FontStyle" xmi:id="_fWfV1SQsEeuD8eTvhiVIwg"/>
+      <styles xmi:type="notation:EObjectValueStyle" xmi:id="_fWfV2SQsEeuD8eTvhiVIwg" name="BASE_ELEMENT">
+        <eObjectValue xmi:type="uml:Class" href="pathmap://UML_METAMODELS/UML.metamodel.uml#Package"/>
+      </styles>
+      <element xsi:nil="true"/>
+      <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_fWfV1iQsEeuD8eTvhiVIwg" points="[0, 0, 0, 0]$[0, 0, 0, 0]"/>
+      <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWfV1yQsEeuD8eTvhiVIwg"/>
+      <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_fWfV2CQsEeuD8eTvhiVIwg"/>
+    </edges>
   </notation:Diagram>
   <notation:Diagram xmi:id="__HqKkJe6EeeiCOWsEr9OuA" type="PapyrusUMLProfileDiagram" name="commPattern" measurementUnit="Pixel">
     <children xmi:type="notation:Shape" xmi:id="_DxmxMJe7EeeiCOWsEr9OuA" type="Stereotype_Shape">
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.uml b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.uml
index 598eaa7..c304a87 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.uml
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/model/robotics.profile.uml
@@ -334,6 +334,15 @@
         <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#Boolean"/>
         <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_srPS8ZQtEeqd8IOJ10ri1Q"/>
       </ownedAttribute>
+      <ownedAttribute xmi:type="uml:Property" xmi:id="_jowcQCQsEeuD8eTvhiVIwg" name="external" visibility="public">
+        <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#Boolean"/>
+        <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_jowcQSQsEeuD8eTvhiVIwg"/>
+        <upperValue xmi:type="uml:LiteralUnlimitedNatural" xmi:id="_ya_hgCQsEeuD8eTvhiVIwg" value="1"/>
+      </ownedAttribute>
+      <ownedAttribute xmi:type="uml:Property" xmi:id="_6e67sCQsEeuD8eTvhiVIwg" name="license" visibility="public">
+        <type xmi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#String"/>
+        <lowerValue xmi:type="uml:LiteralInteger" xmi:id="_6e67sSQsEeuD8eTvhiVIwg"/>
+      </ownedAttribute>
     </packagedElement>
     <packagedElement xmi:type="uml:Extension" xmi:id="_Iwk-IElbEeicede5K86kPg" name="E_ComponentDefinitionModel_Package52" memberEnd="_IwmMQElbEeicede5K86kPg _IwmzUElbEeicede5K86kPg">
       <ownedEnd xmi:type="uml:ExtensionEnd" xmi:id="_IwmMQElbEeicede5K86kPg" name="extension_ComponentDefinitionModel" type="__25AoElaEeicede5K86kPg" aggregation="composite" association="_Iwk-IElbEeicede5K86kPg"/>
@@ -1301,4 +1310,10 @@
   <profileApplication xmi:type="uml:ProfileApplication" xmi:id="_sngToKiFEeerK_UDQFFzLg">
     <appliedProfile xmi:type="uml:Profile" href="pathmap://ROBOTICS_BPC_PROFILES/bpc.profile.uml#_EZ1TgJZ2Eeeq1f8hGgKVzA"/>
   </profileApplication>
+  <profileApplication xmi:type="uml:ProfileApplication" xmi:id="_nIJUQCQsEeuD8eTvhiVIwg">
+    <eAnnotations xmi:type="ecore:EAnnotation" xmi:id="_nIMXkCQsEeuD8eTvhiVIwg" source="http://www.eclipse.org/uml2/2.0.0/UML">
+      <references xmi:type="ecore:EPackage" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#_Kv8EIKFXEeS_KNX0nfvIVQ"/>
+    </eAnnotations>
+    <appliedProfile xmi:type="uml:Profile" href="pathmap://PAPYRUS_ACTIONLANGUAGE_PROFILE/ActionLanguage-Profile.profile.uml#ActionLanguage"/>
+  </profileApplication>
 </uml:Profile>
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/behavior/impl/TaskImpl.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/behavior/impl/TaskImpl.java
index 460acf4..08e2905 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/behavior/impl/TaskImpl.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/behavior/impl/TaskImpl.java
@@ -197,7 +197,6 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
-	@SuppressWarnings("unchecked")
 	@Override
 	public void eSet(int featureID, Object newValue) {
 		switch (featureID) {
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentDefinitionModel.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentDefinitionModel.java
index c64325f..dbc1dfd 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentDefinitionModel.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentDefinitionModel.java
@@ -26,6 +26,8 @@
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getBase_Package <em>Base Package</em>}</li>
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getDependsPackage <em>Depends Package</em>}</li>
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#isRegistered <em>Registered</em>}</li>
+ *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#isExternal <em>External</em>}</li>
+ *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getLicense <em>License</em>}</li>
  * </ul>
  *
  * @see org.eclipse.papyrus.robotics.profile.robotics.components.ComponentsPackage#getComponentDefinitionModel()
@@ -101,4 +103,56 @@
 	 */
 	void setRegistered(boolean value);
 
+	/**
+	 * Returns the value of the '<em><b>External</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>External</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>External</em>' attribute.
+	 * @see #setExternal(boolean)
+	 * @see org.eclipse.papyrus.robotics.profile.robotics.components.ComponentsPackage#getComponentDefinitionModel_External()
+	 * @model dataType="org.eclipse.uml2.types.Boolean" ordered="false"
+	 * @generated
+	 */
+	boolean isExternal();
+
+	/**
+	 * Sets the value of the '{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#isExternal <em>External</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>External</em>' attribute.
+	 * @see #isExternal()
+	 * @generated
+	 */
+	void setExternal(boolean value);
+
+	/**
+	 * Returns the value of the '<em><b>License</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <p>
+	 * If the meaning of the '<em>License</em>' attribute isn't clear,
+	 * there really should be more of a description here...
+	 * </p>
+	 * <!-- end-user-doc -->
+	 * @return the value of the '<em>License</em>' attribute.
+	 * @see #setLicense(String)
+	 * @see org.eclipse.papyrus.robotics.profile.robotics.components.ComponentsPackage#getComponentDefinitionModel_License()
+	 * @model dataType="org.eclipse.uml2.types.String" ordered="false"
+	 * @generated
+	 */
+	String getLicense();
+
+	/**
+	 * Sets the value of the '{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getLicense <em>License</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @param value the new value of the '<em>License</em>' attribute.
+	 * @see #getLicense()
+	 * @generated
+	 */
+	void setLicense(String value);
+
 } // ComponentDefinitionModel
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentsPackage.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentsPackage.java
index e7da772..cf0d136 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentsPackage.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/ComponentsPackage.java
@@ -1330,13 +1330,31 @@
 	int COMPONENT_DEFINITION_MODEL__REGISTERED = BPCPackage.ENTITY_FEATURE_COUNT + 2;
 
 	/**
+	 * The feature id for the '<em><b>External</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int COMPONENT_DEFINITION_MODEL__EXTERNAL = BPCPackage.ENTITY_FEATURE_COUNT + 3;
+
+	/**
+	 * The feature id for the '<em><b>License</b></em>' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 * @ordered
+	 */
+	int COMPONENT_DEFINITION_MODEL__LICENSE = BPCPackage.ENTITY_FEATURE_COUNT + 4;
+
+	/**
 	 * The number of structural features of the '<em>Component Definition Model</em>' class.
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
 	 * @generated
 	 * @ordered
 	 */
-	int COMPONENT_DEFINITION_MODEL_FEATURE_COUNT = BPCPackage.ENTITY_FEATURE_COUNT + 3;
+	int COMPONENT_DEFINITION_MODEL_FEATURE_COUNT = BPCPackage.ENTITY_FEATURE_COUNT + 5;
 
 	/**
 	 * The number of operations of the '<em>Component Definition Model</em>' class.
@@ -2011,6 +2029,28 @@
 	EAttribute getComponentDefinitionModel_Registered();
 
 	/**
+	 * Returns the meta object for the attribute '{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#isExternal <em>External</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>External</em>'.
+	 * @see org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#isExternal()
+	 * @see #getComponentDefinitionModel()
+	 * @generated
+	 */
+	EAttribute getComponentDefinitionModel_External();
+
+	/**
+	 * Returns the meta object for the attribute '{@link org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getLicense <em>License</em>}'.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @return the meta object for the attribute '<em>License</em>'.
+	 * @see org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel#getLicense()
+	 * @see #getComponentDefinitionModel()
+	 * @generated
+	 */
+	EAttribute getComponentDefinitionModel_License();
+
+	/**
 	 * Returns the meta object for class '{@link org.eclipse.papyrus.robotics.profile.robotics.components.SystemComponentArchitectureModel <em>System Component Architecture Model</em>}'.
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
@@ -2402,6 +2442,22 @@
 		EAttribute COMPONENT_DEFINITION_MODEL__REGISTERED = eINSTANCE.getComponentDefinitionModel_Registered();
 
 		/**
+		 * The meta object literal for the '<em><b>External</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute COMPONENT_DEFINITION_MODEL__EXTERNAL = eINSTANCE.getComponentDefinitionModel_External();
+
+		/**
+		 * The meta object literal for the '<em><b>License</b></em>' attribute feature.
+		 * <!-- begin-user-doc -->
+		 * <!-- end-user-doc -->
+		 * @generated
+		 */
+		EAttribute COMPONENT_DEFINITION_MODEL__LICENSE = eINSTANCE.getComponentDefinitionModel_License();
+
+		/**
 		 * The meta object literal for the '{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.SystemComponentArchitectureModelImpl <em>System Component Architecture Model</em>}' class.
 		 * <!-- begin-user-doc -->
 		 * <!-- end-user-doc -->
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ActivityPortImpl.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ActivityPortImpl.java
index e47b7a3..099cc6a 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ActivityPortImpl.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ActivityPortImpl.java
@@ -149,7 +149,6 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
-	@SuppressWarnings("unchecked")
 	@Override
 	public void eSet(int featureID, Object newValue) {
 		switch (featureID) {
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentDefinitionModelImpl.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentDefinitionModelImpl.java
index a16d97d..1ee06cb 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentDefinitionModelImpl.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentDefinitionModelImpl.java
@@ -36,6 +36,8 @@
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.ComponentDefinitionModelImpl#getBase_Package <em>Base Package</em>}</li>
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.ComponentDefinitionModelImpl#getDependsPackage <em>Depends Package</em>}</li>
  *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.ComponentDefinitionModelImpl#isRegistered <em>Registered</em>}</li>
+ *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.ComponentDefinitionModelImpl#isExternal <em>External</em>}</li>
+ *   <li>{@link org.eclipse.papyrus.robotics.profile.robotics.components.impl.ComponentDefinitionModelImpl#getLicense <em>License</em>}</li>
  * </ul>
  *
  * @generated
@@ -82,6 +84,46 @@
 	protected boolean registered = REGISTERED_EDEFAULT;
 
 	/**
+	 * The default value of the '{@link #isExternal() <em>External</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isExternal()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final boolean EXTERNAL_EDEFAULT = false;
+
+	/**
+	 * The cached value of the '{@link #isExternal() <em>External</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #isExternal()
+	 * @generated
+	 * @ordered
+	 */
+	protected boolean external = EXTERNAL_EDEFAULT;
+
+	/**
+	 * The default value of the '{@link #getLicense() <em>License</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getLicense()
+	 * @generated
+	 * @ordered
+	 */
+	protected static final String LICENSE_EDEFAULT = null;
+
+	/**
+	 * The cached value of the '{@link #getLicense() <em>License</em>}' attribute.
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @see #getLicense()
+	 * @generated
+	 * @ordered
+	 */
+	protected String license = LICENSE_EDEFAULT;
+
+	/**
 	 * <!-- begin-user-doc -->
 	 * <!-- end-user-doc -->
 	 * @generated
@@ -176,6 +218,48 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
+	public boolean isExternal() {
+		return external;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setExternal(boolean newExternal) {
+		boolean oldExternal = external;
+		external = newExternal;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, ComponentsPackage.COMPONENT_DEFINITION_MODEL__EXTERNAL, oldExternal, external));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public String getLicense() {
+		return license;
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public void setLicense(String newLicense) {
+		String oldLicense = license;
+		license = newLicense;
+		if (eNotificationRequired())
+			eNotify(new ENotificationImpl(this, Notification.SET, ComponentsPackage.COMPONENT_DEFINITION_MODEL__LICENSE, oldLicense, license));
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
 	@Override
 	public Object eGet(int featureID, boolean resolve, boolean coreType) {
 		switch (featureID) {
@@ -186,6 +270,10 @@
 				return getDependsPackage();
 			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__REGISTERED:
 				return isRegistered();
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__EXTERNAL:
+				return isExternal();
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__LICENSE:
+				return getLicense();
 		}
 		return super.eGet(featureID, resolve, coreType);
 	}
@@ -209,6 +297,12 @@
 			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__REGISTERED:
 				setRegistered((Boolean)newValue);
 				return;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__EXTERNAL:
+				setExternal((Boolean)newValue);
+				return;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__LICENSE:
+				setLicense((String)newValue);
+				return;
 		}
 		super.eSet(featureID, newValue);
 	}
@@ -230,6 +324,12 @@
 			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__REGISTERED:
 				setRegistered(REGISTERED_EDEFAULT);
 				return;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__EXTERNAL:
+				setExternal(EXTERNAL_EDEFAULT);
+				return;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__LICENSE:
+				setLicense(LICENSE_EDEFAULT);
+				return;
 		}
 		super.eUnset(featureID);
 	}
@@ -248,6 +348,10 @@
 				return dependsPackage != null && !dependsPackage.isEmpty();
 			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__REGISTERED:
 				return registered != REGISTERED_EDEFAULT;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__EXTERNAL:
+				return external != EXTERNAL_EDEFAULT;
+			case ComponentsPackage.COMPONENT_DEFINITION_MODEL__LICENSE:
+				return LICENSE_EDEFAULT == null ? license != null : !LICENSE_EDEFAULT.equals(license);
 		}
 		return super.eIsSet(featureID);
 	}
@@ -266,6 +370,10 @@
 		result.append(dependsPackage);
 		result.append(", registered: "); //$NON-NLS-1$
 		result.append(registered);
+		result.append(", external: "); //$NON-NLS-1$
+		result.append(external);
+		result.append(", license: "); //$NON-NLS-1$
+		result.append(license);
 		result.append(')');
 		return result.toString();
 	}
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentsPackageImpl.java b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentsPackageImpl.java
index 60fb7da..9ab9b01 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentsPackageImpl.java
+++ b/plugins/customization/org.eclipse.papyrus.robotics.profile/src-gen/org/eclipse/papyrus/robotics/profile/robotics/components/impl/ComponentsPackageImpl.java
@@ -612,6 +612,24 @@
 	 * <!-- end-user-doc -->
 	 * @generated
 	 */
+	public EAttribute getComponentDefinitionModel_External() {
+		return (EAttribute)componentDefinitionModelEClass.getEStructuralFeatures().get(3);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
+	public EAttribute getComponentDefinitionModel_License() {
+		return (EAttribute)componentDefinitionModelEClass.getEStructuralFeatures().get(4);
+	}
+
+	/**
+	 * <!-- begin-user-doc -->
+	 * <!-- end-user-doc -->
+	 * @generated
+	 */
 	public EClass getSystemComponentArchitectureModel() {
 		return systemComponentArchitectureModelEClass;
 	}
@@ -719,6 +737,8 @@
 		createEReference(componentDefinitionModelEClass, COMPONENT_DEFINITION_MODEL__BASE_PACKAGE);
 		createEAttribute(componentDefinitionModelEClass, COMPONENT_DEFINITION_MODEL__DEPENDS_PACKAGE);
 		createEAttribute(componentDefinitionModelEClass, COMPONENT_DEFINITION_MODEL__REGISTERED);
+		createEAttribute(componentDefinitionModelEClass, COMPONENT_DEFINITION_MODEL__EXTERNAL);
+		createEAttribute(componentDefinitionModelEClass, COMPONENT_DEFINITION_MODEL__LICENSE);
 
 		systemComponentArchitectureModelEClass = createEClass(SYSTEM_COMPONENT_ARCHITECTURE_MODEL);
 		createEReference(systemComponentArchitectureModelEClass, SYSTEM_COMPONENT_ARCHITECTURE_MODEL__BASE_PACKAGE);
@@ -825,6 +845,8 @@
 		initEReference(getComponentDefinitionModel_Base_Package(), theUMLPackage.getPackage(), null, "base_Package", null, 1, 1, ComponentDefinitionModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
 		initEAttribute(getComponentDefinitionModel_DependsPackage(), theTypesPackage.getString(), "dependsPackage", null, 0, -1, ComponentDefinitionModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
 		initEAttribute(getComponentDefinitionModel_Registered(), theTypesPackage.getBoolean(), "registered", null, 0, 1, ComponentDefinitionModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
+		initEAttribute(getComponentDefinitionModel_External(), theTypesPackage.getBoolean(), "external", null, 0, 1, ComponentDefinitionModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
+		initEAttribute(getComponentDefinitionModel_License(), theTypesPackage.getString(), "license", null, 0, 1, ComponentDefinitionModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
 
 		initEClass(systemComponentArchitectureModelEClass, SystemComponentArchitectureModel.class, "SystemComponentArchitectureModel", !IS_ABSTRACT, !IS_INTERFACE, IS_GENERATED_INSTANCE_CLASS); //$NON-NLS-1$
 		initEReference(getSystemComponentArchitectureModel_Base_Package(), theUMLPackage.getPackage(), null, "base_Package", null, 1, 1, SystemComponentArchitectureModel.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, !IS_ORDERED); //$NON-NLS-1$
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/compdef/ui/SingleComponentDefinitionModel.xwt b/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/compdef/ui/SingleComponentDefinitionModel.xwt
index f439d0a..bcaaf55 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/compdef/ui/SingleComponentDefinitionModel.xwt
+++ b/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/compdef/ui/SingleComponentDefinitionModel.xwt
@@ -8,11 +8,19 @@
 	</Composite.layout>
 	<Composite>
 		<Composite.layout>
-			<ppel:PropertiesLayout numColumns="1"></ppel:PropertiesLayout>
+			<ppel:PropertiesLayout numColumns="2"></ppel:PropertiesLayout>
 		</Composite.layout>
 		<ppe:BooleanRadio input="{Binding}"
 			property="robotics:components:ComponentDefinitionModel:registered"
 			customLabel="Registered component"></ppe:BooleanRadio>
+		<ppe:BooleanRadio input="{Binding}"
+			property="robotics:components:ComponentDefinitionModel:external"
+			customLabel="External component"></ppe:BooleanRadio>
+	</Composite>
+	<Composite>
+		<Composite.layout>
+			<ppel:PropertiesLayout numColumns="1"></ppel:PropertiesLayout>
+		</Composite.layout>
 		<ppe:MultiString input="{Binding}"
 			property="robotics:components:ComponentDefinitionModel:dependsPackage"
 			customLabel="ROS2 package dependencies"></ppe:MultiString>
diff --git a/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/robotics/robotics.ctx b/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/robotics/robotics.ctx
index 719e039..856bb87 100644
--- a/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/robotics/robotics.ctx
+++ b/plugins/customization/org.eclipse.papyrus.robotics.properties/properties/robotics/robotics.ctx
@@ -63,6 +63,7 @@
       </elements>
       <elements xmi:id="datactx.robotics.components.componentdefinitionmodel" name="ComponentDefinitionModel">
         <properties xmi:id="datactx.robotics.components.componentdefinitionmodel.registered" name="registered"/>
+        <properties xmi:id="datactx.robotics.components.componentdefinitionmodel.external" name="external"/>
         <properties xmi:id="datactx.robotics.components.componentdefinitionmodel.dependspackage" name="dependsPackage"  multiplicity="-1"/>
       </elements>
     </elements>
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
index 654fdee..6dc859a 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.base/src/org/eclipse/papyrus/robotics/ros2/base/EnvironmentUtils.java
@@ -172,9 +172,7 @@
 	}
 	
 	@SuppressWarnings("nls")
-	public static void selectAndSourceScript(String initialFile) {
-		final Shell shell = Display.getCurrent().getActiveShell();
-		// new FileSelectionDialog(Display.getCurrent().getActiveShell(), "*.x", "select")
+	public static void selectAndSourceScript(String initialFile, Shell shell) {
 		if (shell != null) {
 			FileDialog fd = new FileDialog(shell, SWT.OPEN);
 			fd.setText("Open");
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/MessageUtils.xtend b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/MessageUtils.xtend
index f3ed045..b5271a3 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/MessageUtils.xtend
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.codegen/src/org/eclipse/papyrus/robotics/ros2/codegen/utils/MessageUtils.xtend
@@ -65,6 +65,10 @@
 	 * ServiceDefinitionModel stereotype
 	 */
 	def static getMessagePackage(NamedElement ne) {
+		if (ne === null || ne.eIsProxy) {
+			return null
+		}
+		
 		var Element pkg = ne.nearestPackage
 		while (pkg instanceof Package) {
 			if (StereotypeUtil.isApplied(pkg, ServiceDefinitionModel)) {
@@ -384,7 +388,7 @@
 		for (component : components) {
 			for (port : PortUtils.getAllPorts(component)) {
 				val pkg = port.serviceDefinition.messagePackage
-				if (!list.contains(pkg)) {
+				if (pkg !== null && !list.contains(pkg)) {
 					list.add(pkg)
 				}
 			}
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/META-INF/MANIFEST.MF b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/META-INF/MANIFEST.MF
index 5a6e628..c2aac9a 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/META-INF/MANIFEST.MF
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/META-INF/MANIFEST.MF
@@ -37,7 +37,8 @@
  org.eclipse.emf.transaction;bundle-version="1.9.0",
  org.eclipse.papyrus.infra.gmfdiag.common;bundle-version="[3.1.0,5.0.0)",
  org.eclipse.papyrus.infra.core;bundle-version="[3.1.0,5.0.0)",
- org.eclipse.gmf.runtime.notation;bundle-version="1.10.0"
+ org.eclipse.gmf.runtime.notation;bundle-version="1.10.0",
+ org.eclipse.papyrus.robotics.ros2.codegen;bundle-version="0.8.0"
 Bundle-Vendor: %providerName
 Bundle-ActivationPolicy: lazy
 Bundle-Version: 0.8.0.qualifier
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/plugin.xml b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/plugin.xml
index a506be5..0f1c0d7 100644
--- a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/plugin.xml
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/plugin.xml
@@ -7,7 +7,7 @@
 			categoryId="org.eclipse.papyrus.editor.category"
 			defaultHandler="org.eclipse.papyrus.robotics.ros2.reverse.handlers.ReverseMessagesHandler"
 			id="org.eclipse.papyrus.robotics.ros2.reverse.menuActions.ReverseMessagesCmd"
-			name="Reverse ROS messages"/>
+			name="Reverse ROS messages and services"/>
 		<command
 			categoryId="org.eclipse.papyrus.editor.category"
 			defaultHandler="org.eclipse.papyrus.robotics.ros2.reverse.handlers.ReverseNodesHandler"
@@ -18,6 +18,11 @@
 			defaultHandler="org.eclipse.papyrus.robotics.ros2.reverse.handlers.ReverseNodeFromFileHandler"
 			id="org.eclipse.papyrus.robotics.ros2.reverse.menuActions.ReverseNodeFromFileCmd"
 			name="Reverse ROS node from C++ file (body)"/>
+		<command
+			categoryId="org.eclipse.papyrus.editor.category"
+			defaultHandler="org.eclipse.papyrus.robotics.ros2.reverse.handlers.ReverseNodesFromWorkspaceHandler"
+			id="org.eclipse.papyrus.robotics.ros2.reverse.menuActions.ReverseNodesFromWorkspaceCmd"
+			name="Reverse ROS nodes from a ROS2 workspace"/>
 	</extension>
 	<extension point="org.eclipse.ui.menus">
 		<menuContribution
@@ -35,6 +40,10 @@
 				commandId="org.eclipse.papyrus.robotics.ros2.reverse.menuActions.ReverseNodeFromFileCmd"
 				icon="platform:/plugin/org.eclipse.papyrus.robotics.ros2.codegen/icons/ros-16x16.png">
 			</command>
+			<command
+				commandId="org.eclipse.papyrus.robotics.ros2.reverse.menuActions.ReverseNodesFromWorkspaceCmd"
+				icon="platform:/plugin/org.eclipse.papyrus.robotics.ros2.codegen/icons/ros-16x16.png">
+			</command>
 		</menuContribution>
 	</extension>
 </plugin>
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/CheckNodeInheritance.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/CheckNodeInheritance.java
new file mode 100644
index 0000000..5aa02b0
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/CheckNodeInheritance.java
@@ -0,0 +1,113 @@
+/*****************************************************************************
+ * 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 org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
+import org.eclipse.cdt.core.dom.ast.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
+import org.eclipse.cdt.core.model.CModelException;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.IMethod;
+import org.eclipse.cdt.core.model.INamespace;
+import org.eclipse.cdt.core.model.IParent;
+import org.eclipse.cdt.core.model.ISourceRange;
+import org.eclipse.cdt.core.model.ITranslationUnit;
+import org.eclipse.papyrus.designer.deployment.tools.Activator;
+
+/**
+ * Check, whether the class defined in the translation extends Node or LifecycleNode
+ */
+public class CheckNodeInheritance {
+
+	protected static final String LIFECYCLE_NODE = "rclcpp_lifecycle::LifecycleNode"; //$NON-NLS-1$
+
+	protected static final String NODE = "rclcpp::Node"; //$NON-NLS-1$
+
+	protected IASTNodeSelector selector;
+
+	public CheckNodeInheritance(IASTTranslationUnit ast) {
+		selector = ast.getNodeSelector(null);
+	}
+
+	public boolean isNode(ITranslationUnit itu) {
+		try {
+			ICPPClassType classType = findClass(itu);
+			if (classType != null) {
+				return isNode(classType);
+			}
+		} catch (CModelException e) {
+			Activator.log.error(e);
+		}
+		return false;
+	}
+
+	/**
+	 * Obtain class from ITU or namespace. The class finds the first method and then obtains the
+	 * class from its declaration
+	 *
+	 * @param parent
+	 *            a translation unit or namespace
+	 * @return the found class or null, if no method or the associated association is not found
+	 * @throws CModelException
+	 */
+	public ICPPClassType findClass(IParent parent) throws CModelException {
+		ICPPClassType classType = null;
+		for (ICElement child : parent.getChildren()) {
+			if (child instanceof INamespace) {
+				// recurse into namespace
+				classType = findClass((INamespace) child);
+			} else if (child instanceof IMethod) {
+				IMethod method = (IMethod) child;
+				ISourceRange range = method.getSourceRange();
+				IASTNode node = selector.findEnclosingNode(range.getStartPos(), range.getLength());
+
+				if (node instanceof IASTFunctionDefinition) {
+					IASTFunctionDefinition fctDef = (IASTFunctionDefinition) node;
+					IBinding binding = fctDef.getDeclarator().getName().resolveBinding();
+					if (binding instanceof ICPPMember) {
+						classType = ((ICPPMember) binding).getClassOwner();
+					}
+				}
+				if (classType != null) {
+					return classType;
+				}
+			}
+		}
+		return classType;
+	}
+
+	public boolean isNode(ICPPClassType classType) {
+		for (ICPPBase base : classType.getBases()) {
+			IType baseClass = base.getBaseClassType();
+			if (baseClass.toString().equals(LIFECYCLE_NODE) ||
+				baseClass.toString().equals(NODE)) {
+				return true;
+			}
+			// TODO: name based check is not reliable
+			if (baseClass instanceof ICPPClassType) {
+				boolean isNode = isNode((ICPPClassType) baseClass);
+				if (isNode) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+}
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
index 959309e..366a751 100644
--- 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
@@ -43,6 +43,7 @@
 import org.eclipse.papyrus.infra.gmfdiag.common.model.NotationModel;
 import org.eclipse.papyrus.robotics.core.utils.FileExtensions;
 import org.eclipse.papyrus.robotics.core.utils.ScanUtils;
+import org.eclipse.papyrus.robotics.profile.robotics.components.ComponentDefinitionModel;
 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;
@@ -50,6 +51,7 @@
 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.papyrus.uml.tools.utils.StereotypeUtil;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.uml2.uml.Class;
 import org.eclipse.uml2.uml.Package;
@@ -69,6 +71,10 @@
 	}
 	
 	public void reverseNode(IProgressMonitor monitor) {
+		reverseNode(monitor, null);
+	}
+
+	public void reverseNode(IProgressMonitor monitor, IProject project) {
 		IIndex index = null;
 		try {
 			String pkgName = null;
@@ -103,20 +109,28 @@
 			
 			IASTTranslationUnit ast = itu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS);
 			monitor.worked(1);
-
+			CheckNodeInheritance checkNode = new CheckNodeInheritance(ast);
+			
+			if (!checkNode.isNode(itu)) {
+				// no node => exit
+				return;
+			}
+			
 			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);
+				IProject projectCandidate = FolderUtils.obtainProject(fileName);
 				if (project != null) {
-					pkgName = project.getName();
+					pkgName = projectCandidate.getName();
 				} else {
 					pkgName = name;
 				}
 			}
 
-			IProject project = root.getProject(pkgName);
+			if (project == null) {
+				project = root.getProject(pkgName);
+			}
 			IProgressMonitor progressMonitor = new NullProgressMonitor();
 			if (!project.exists()) {
 				project.create(progressMonitor);
@@ -141,7 +155,7 @@
 				});
 			}
 			if (writeModel) {
-				URI newURI = URI.createURI("platform:/resource/" + pkgName + "/models/components/" + fileName);
+				URI newURI = URI.createURI("platform:/resource/" + project.getName() + "/models/components/" + fileName);
 				ModelTemplate mt = new ModelTemplate(newURI, "compdef");
 				final NotationModel notation = mt.getNotationModel();
 
@@ -156,6 +170,8 @@
 					@Override
 					protected void doExecute() {
 						pkg.setName(pkgNameFinal);
+						ComponentDefinitionModel cdm = StereotypeUtil.applyApp(pkg, ComponentDefinitionModel.class);
+						cdm.setExternal(true);
 
 						Class clazz = (Class) pkg.getOwnedType(ReverseConstants.MODEL_NAME_UC);
 						clazz.setName(nameFinal);
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodesFromWorkspace.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodesFromWorkspace.java
new file mode 100644
index 0000000..1434090
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/fromfile/ReverseNodesFromWorkspace.java
@@ -0,0 +1,82 @@
+/*****************************************************************************
+ * 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 org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.papyrus.robotics.ros2.reverse.Activator;
+
+/**
+ * Reverse a whole ROS2 workspace from source
+ */
+public class ReverseNodesFromWorkspace {
+
+	protected static final String CPP = ".cpp"; //$NON-NLS-1$
+
+	public static final String SRC = "src"; //$NON-NLS-1$
+
+	protected IProject project;
+
+	protected IProgressMonitor monitor;
+
+	
+	public ReverseNodesFromWorkspace(IProject project) {
+		this.project = project;
+	}
+
+	public void reverseWorkspace(IProgressMonitor monitor) {
+		this.monitor = monitor;
+		try {
+			// IFolder srcFolder = folder.getFolder(SRC);
+			// IProject srcFolder = folder;
+			// if (srcFolder != null) {
+				for (IResource rosPkg : project.members()) {
+					if (rosPkg instanceof IFolder) {
+						reverseRosPkg((IFolder) rosPkg);
+					}
+				}
+			// }
+		} catch (CoreException e) {
+			Activator.log.error(e);
+		}
+	}
+
+	public void reverseRosPkg(IFolder rosPkg) throws CoreException {
+		IFolder srcFolder = rosPkg.getFolder(SRC);
+		if (srcFolder != null && srcFolder.exists()) {
+			scanFiles(srcFolder);
+		}
+	}
+	
+	public void scanFiles(IFolder srcFolder) throws CoreException {
+		for (IResource member : srcFolder.members()) {
+			if (monitor.isCanceled()) {
+				break;
+			}
+			if (member instanceof IFolder) {
+				scanFiles((IFolder) member);
+			}
+			else if (member instanceof IFile && member.getName().endsWith(CPP)) {
+				monitor.subTask(String.format("analyze file %s", member.getName()));
+				monitor.worked(1);
+				ReverseNodeFromSource rn = new ReverseNodeFromSource((IFile) member);
+				rn.reverseNode(monitor, project);
+			}
+		}
+	}
+}
\ 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
index b3b33c3..712e7a9 100644
--- 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
@@ -32,16 +32,16 @@
 import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
 import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
 import org.eclipse.cdt.core.dom.ast.IBinding;
-import org.eclipse.cdt.core.dom.ast.IField;
 import org.eclipse.cdt.core.dom.ast.IType;
+import org.eclipse.cdt.core.dom.ast.IVariable;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding;
 import org.eclipse.cdt.internal.core.model.ASTStringUtil;
 import org.eclipse.emf.common.util.URI;
 import org.eclipse.emf.ecore.resource.ResourceSet;
 import org.eclipse.papyrus.designer.languages.common.base.ElementUtils;
-import org.eclipse.papyrus.designer.languages.common.base.StringUtils;
 import org.eclipse.papyrus.designer.languages.common.base.StdUriConstants;
+import org.eclipse.papyrus.designer.languages.common.base.StringUtils;
 import org.eclipse.papyrus.robotics.core.utils.ParameterUtils;
 import org.eclipse.papyrus.robotics.profile.robotics.parameters.ParameterEntry;
 import org.eclipse.papyrus.robotics.ros2.reverse.ParamInfo;
@@ -65,7 +65,7 @@
 	protected IASTTranslationUnit ast;
 
 	/**
-	 * a parameter info list (in addition to the map below, to 
+	 * a parameter info list (in addition to the map below, to
 	 * preserve the order of the entries
 	 */
 	protected List<ParamInfo> paramInfos;
@@ -92,7 +92,7 @@
 		}
 		return paramInfo;
 	}
-	
+
 	public List<ParamInfo> getParamInfos() {
 		return paramInfos;
 	}
@@ -224,12 +224,13 @@
 			if (arguments[1] instanceof IASTIdExpression) {
 				IASTIdExpression id = (IASTIdExpression) arguments[1];
 				IBinding binding = id.getName().resolveBinding();
-				IType type = ((IField) binding).getType();
-				if (type instanceof ICPPBinding) {
-					typeName = ASTTypeUtil.getQualifiedName((ICPPBinding) type);
-				}
-				else {
-					typeName = type.toString();
+				if (binding instanceof IVariable) {
+					IType type = ((IVariable) binding).getType();
+					if (type instanceof ICPPBinding) {
+						typeName = ASTTypeUtil.getQualifiedName((ICPPBinding) type);
+					} else {
+						typeName = type.toString();
+					}
 				}
 			}
 		}
@@ -239,10 +240,10 @@
 			// loaded by template
 			PackageUtil.loadPackage(StdUriConstants.UML_PRIM_TYPES_URI, rs);
 			PackageUtil.loadPackage(URI.createURI("pathmap://ROS2_LIBRARY/ros2Library.uml")/* Helpers.ROS_LIBRARY_URI */, rs);
-			
+
 			// can the element be retrieved directly?
 			NamedElement ne = ElementUtils.getQualifiedElementFromRS(component, typeName);
-			
+
 			if (ne == null) {
 				// check whether in AnsiCLibrary
 				String qName = "AnsiCLibrary" + NamedElement.SEPARATOR + typeName;
@@ -251,11 +252,12 @@
 			if (ne == null) {
 				// try stdlib in ros2 library. Only retrieve stdlib, since ElementUtils do not
 				// handle separator in type name (as in vector<std::string>)
+				// (depending on CDT version, __cxx11 namespace is provided)
 				String shortName = null;
-				if (typeName.equals("std::__cxx11::string")) {
+				if (typeName.equals("std::__cxx11::string") ||
+						typeName.equals("std::string")) {
 					shortName = "string";
-				}
-				else if (typeName.equals("std::vector<string,allocator<string>>")) {
+				} else if (typeName.equals("std::vector<string,allocator<string>>")) {
 					shortName = "vector<std::string>";
 				}
 				if (shortName != null) {
@@ -269,8 +271,7 @@
 				ParamInfo paramInfo = getParamInfo(paramName);
 				paramInfo.name = paramName;
 				paramInfo.type = (Type) ne;
-			}
-			else {
+			} else {
 				Activator.log.debug(String.format("Cannot find type %s", typeName));
 			}
 		}
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
index b2b8251..2564ecf 100644
--- 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
@@ -17,6 +17,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
 import org.eclipse.cdt.core.dom.ast.IASTExpression;
 import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
 import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
@@ -26,6 +27,9 @@
 import org.eclipse.cdt.core.dom.ast.IASTName;
 import org.eclipse.cdt.core.dom.ast.IASTNode;
 import org.eclipse.cdt.core.dom.ast.IASTTypeId;
+import org.eclipse.cdt.core.dom.ast.IBinding;
+import org.eclipse.cdt.core.dom.ast.ITypedef;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
 import org.eclipse.cdt.core.model.ITranslationUnit;
@@ -73,12 +77,25 @@
 
 		for (PortInfo pi : portInfoList) {
 			String nameArray[] = pi.dtQName.split(Namespace.SEPARATOR);
-			String pkgName = nameArray[0];
-			String sdName = nameArray[2];
+			String pkgName;
+			String sdName;
+			// we expect that the name is a fully qualified message name <pkgName::[msg|srv]::name>
+			if (nameArray.length > 2) {
+				pkgName = nameArray[0];
+				sdName = nameArray[2];
+			}
+			else {
+				// rudimentary handling of other cases (e.g. if project setup is incorrect)
+				pkgName = "*"; //$NON-NLS-1$
+				sdName = pi.dtQName;
+			}
 			Interface sd = ServiceDefUtils.getServiceDef(clazz, pathMapURIs, pi.pk, pkgName, sdName);
 			if (sd != null) {
 				CreatePortUtils.createPort(clazz, pi, sd);
 			}
+			else {
+				Activator.log.debug(String.format("Cannot find service <%s>", pi.dtQName));  //$NON-NLS-1$
+			}
 		}
 	}
 
@@ -147,7 +164,18 @@
 			portInfo.pk = pk;
 			IASTNode argument = templateId.getTemplateArguments()[0];
 			if (argument instanceof IASTTypeId) {
-				portInfo.dtQName = ((IASTTypeId) argument).getDeclSpecifier().toString();
+				IASTDeclSpecifier declSpecifier = ((IASTTypeId) argument).getDeclSpecifier();
+				if (declSpecifier instanceof ICPPASTNamedTypeSpecifier) {
+					// handle case that type is defined via "using" statement
+					IBinding binding = ((ICPPASTNamedTypeSpecifier) declSpecifier).getName().resolveBinding();
+					// but exclude typedef (as all messages or services are typedefs
+					if (binding != null && !(binding instanceof ITypedef)) {
+						portInfo.dtQName = binding.toString();
+					}
+				}
+				if (portInfo.dtQName == null) {
+					portInfo.dtQName = ((IASTTypeId) argument).getDeclSpecifier().toString();
+				}
 			} else {
 				Activator.log.debug("Unexpected template argument"); //$NON-NLS-1$
 			}
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 a6a2617..aa972ea 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
@@ -65,7 +65,7 @@
 				"Do you want to \"source\" an additional setup.sh script" +
 				"before starting the reverse (typically in the install folder of a ROS2 workspace)");
 		if (sourceSh) {
-			EnvironmentUtils.selectAndSourceScript(container.getLocation().toString());
+			EnvironmentUtils.selectAndSourceScript(container.getLocation().toString(), shell);
 		}
 		Job job = new Job("Reverse ROS messages and services") { //$NON-NLS-1$
 			@Override
diff --git a/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesFromWorkspaceHandler.java b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesFromWorkspaceHandler.java
new file mode 100644
index 0000000..84e9da0
--- /dev/null
+++ b/plugins/ros2/org.eclipse.papyrus.robotics.ros2.reverse/src/org/eclipse/papyrus/robotics/ros2/reverse/handlers/ReverseNodesFromWorkspaceHandler.java
@@ -0,0 +1,82 @@
+/*****************************************************************************
+ * 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.IProject;
+import org.eclipse.core.runtime.IAdaptable;
+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.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.papyrus.designer.transformation.core.transformations.TransformationContext;
+import org.eclipse.papyrus.robotics.ros2.codegen.utils.ProjectTools;
+import org.eclipse.papyrus.robotics.ros2.reverse.fromfile.ReverseNodesFromWorkspace;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+public class ReverseNodesFromWorkspaceHandler extends AbstractHandler {
+
+	protected IProject project;
+
+	@Override
+	public boolean isEnabled() {
+		// Retrieve selected elements
+		IStructuredSelection selection = (IStructuredSelection) PlatformUI
+				.getWorkbench().getActiveWorkbenchWindow()
+				.getSelectionService().getSelection();
+
+		Object selected = selection.getFirstElement();
+		if (selected instanceof IAdaptable) {
+			selected = ((IAdaptable) selected).getAdapter(IProject.class);
+		}
+		if (selected instanceof IProject) {
+			project = (IProject) selected;
+			return true;
+		}
+		return false;
+	}
+
+	@Override
+	public Object execute(ExecutionEvent arg0) throws ExecutionException {
+		final Shell shell = Display.getCurrent().getActiveShell();
+		final boolean configureCDT =
+			MessageDialog.openQuestion(shell, "Configure CDT project?",
+				"Do you want to configure this project with CDT settings corresponding to the current setup?");
+			
+		Job job = new Job("Reverse node from workspace") { //$NON-NLS-1$
+			@Override
+			protected IStatus run(final IProgressMonitor monitor) {
+				
+				if (configureCDT) {
+					TransformationContext.monitor = monitor;
+					ProjectTools.configureCDT(project, project.getName());
+				}
+				ReverseNodesFromWorkspace reverseFromSource =
+						new ReverseNodesFromWorkspace(project);
+				reverseFromSource.reverseWorkspace(monitor);
+				return Status.OK_STATUS;
+			}
+		};
+		job.schedule();
+
+		return null;
+	}
+}