Bug 538475 - [Designer] [C Generator] Includes of dependencies are not
generated

- Generate required classifiers
- Generate includes and declares of required classifiers
- Fix generation of includes in header and body

Conflicts:
	languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/module/classModuleScript.xtend

Change-Id: Ia5908ea7c172e5424b7a0cdc732f680c38528777
Signed-off-by: Shuai Li <shuai.li@cea.fr>
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen.ui/src/org/eclipse/papyrus/designer/languages/c/codegen/ui/handlers/GenerateCodeHandler.java b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen.ui/src/org/eclipse/papyrus/designer/languages/c/codegen/ui/handlers/GenerateCodeHandler.java
index 7a574d6..20d52a4 100644
--- a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen.ui/src/org/eclipse/papyrus/designer/languages/c/codegen/ui/handlers/GenerateCodeHandler.java
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen.ui/src/org/eclipse/papyrus/designer/languages/c/codegen/ui/handlers/GenerateCodeHandler.java
@@ -23,6 +23,7 @@
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.papyrus.designer.languages.c.codegen.transformation.CModelElementsCreator;
 import org.eclipse.papyrus.designer.languages.c.codegen.utils.LocateCProject;
+import org.eclipse.papyrus.designer.languages.common.base.ClassUtils;
 import org.eclipse.papyrus.uml.diagram.common.handlers.CmdHandler;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.uml2.uml.Classifier;
@@ -76,16 +77,16 @@
 		mec.createPackageableElement(pe, null, recurse);
 		// Eventual refresh is done in createPackageableElement
 	
-		/*
+		
 		if (pe instanceof Classifier) {
-			EList<Classifier> requiredClassifiers = ClassUtils.includedClassifiers((Classifier) pe);
+			EList<Classifier> requiredClassifiers = ClassUtils.requiredClassifiers((Classifier) pe);
 			for (Classifier requiredClassifier : requiredClassifiers) {
 				if (!alreadyHandled.contains(requiredClassifier)) {
 					generate(mec, requiredClassifier, alreadyHandled, false);
 				}
 			}
 		}
-		*/
+
 		// owning package is required by generated code.
 		Package owningPackage = pe.getNearestPackage();
 		if ((owningPackage != null) && (owningPackage != pe)) {
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/classHeaderScript.xtend b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/classHeaderScript.xtend
index fe2c9c4..eb1ee97 100644
--- a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/classHeaderScript.xtend
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/classHeaderScript.xtend
@@ -31,16 +31,13 @@
 
 class classHeaderScript {
 	def static classHeaderScript(Class clazz) '''
-		// This template is called by the main module file 
+		««« This template is called by the main module file 
 		«clazz.genHeading»
 		
 		«clazz.genHeadingHeader»
 		
-		// Explicit import of the class
-		«clazz.genImport»
-		«clazz.genInclude»
+		«clazz.genHeaderIncludes»
 		
-		// header body
 		«clazz.classHeaderBody»
 		
 		«clazz.genEndHeader»
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/dataTypeHeaderScript.xtend b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/dataTypeHeaderScript.xtend
index 4291dc4..08f8b1d 100644
--- a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/dataTypeHeaderScript.xtend
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/header/dataTypeHeaderScript.xtend
@@ -33,7 +33,7 @@
 		«dataType.genHeadingHeader»
 		
 		// Explicit import of the class
-		«dataType.genImport»
+		«dataType.genHeaderIncludes»
 		
 		// header body
 		«dataType.dataTypeHeaderBody»
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/lib/importScript.xtend b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/lib/importScript.xtend
index ba824c9..a33dd93 100644
--- a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/lib/importScript.xtend
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/lib/importScript.xtend
@@ -12,119 +12,253 @@
 package org.eclipse.papyrus.designer.languages.c.codegen.lib
 
 import java.util.ArrayList
-import org.eclipse.uml2.uml.Class
-import org.eclipse.uml2.uml.Classifier
-import org.eclipse.uml2.uml.DataType
-import org.eclipse.uml2.uml.Element
-import org.eclipse.uml2.uml.Interface
-import org.eclipse.uml2.uml.NamedElement
-import org.eclipse.uml2.uml.Namespace
-import org.eclipse.uml2.uml.Package
-import org.eclipse.uml2.uml.profile.standard.ModelLibrary
-
-import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.commonScript.*
-import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.interfaceScript.*
-import static extension org.eclipse.papyrus.designer.languages.c.codegen.services.UmlCommentServices.*
-import static extension org.eclipse.papyrus.designer.languages.common.base.GenUtils.*
+import java.util.List
+import org.eclipse.emf.common.util.EList
+import org.eclipse.papyrus.designer.languages.c.codegen.preferences.CCodeGenUtils
+import org.eclipse.papyrus.designer.languages.common.base.GenUtils
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.CppRoot
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.ExternLibrary
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.External
 import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Include
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.NoCodeGen
+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Template
+import org.eclipse.uml2.uml.Classifier
+import org.eclipse.uml2.uml.Enumeration
+import org.eclipse.uml2.uml.NamedElement
+import org.eclipse.uml2.uml.Package
+import org.eclipse.uml2.uml.PrimitiveType
+import org.eclipse.uml2.uml.util.UMLUtil
+
+import static extension org.eclipse.papyrus.designer.languages.c.codegen.services.UmlCommentServices.*
+import org.eclipse.papyrus.designer.languages.c.codegen.utils.CClassUtils
 
 class importScript {
-	def public static genImport(Classifier classifier) '''
-		«classifier.partComment('Import')»
-		«classifier.genImportList()» «classifier.genDynamicInstanciationImport()» 
-		// User imports
-		/* "startUserCode"   to add imports */
-		/* "endUserCode"     to add imports */
-	'''
-	def public static genInclude(NamedElement namedElement) '''
-		/* include other files*/
-		«IF namedElement.hasStereotype(Include)»
-			«var include = namedElement.getApplicableStereotype("C_Cpp::Include")»
-			«namedElement.getValue(include, "body")»
-		«ENDIF»		
-	'''
-
-	def public static genImportList(Classifier classifier) '''
-		«FOR import_ : classifier.getImportList»
-			«import_.genRelativeNamedImport(classifier)»
+	def public static genHeaderIncludes(Classifier classifier) '''
+		«classifier.partComment('Includes and declares')»
+		««« Derived includes from required classifiers that are not pointers
+		// Derived includes
+		«FOR path : CClassAllIncludesHeader(classifier).sort»
+			«includeDirective(path)»
 		«ENDFOR»
+		// End of Derived includes
+		
+		««« Derived includes from required classifiers that are pointers
+		// Derived declares
+		«FOR path : CClassAllDeclares(classifier).sort» 
+			«declareDirective(path)»
+		«ENDFOR»
+		// End of Derived declares
+		
+		««« Includes from <<Include>> stereotype's header attribute
+		«classifier.CIncludeHeader()»
+		
+		««« Includes stdio and stdlib
+		// Std headers
+		«genStdInclude()» 
+		// End of Std headers
 	'''
 
-
-	def public static getImportList(Classifier classifier) {
-		classifier.genNamespaceImports + classifier.genOwningPackageImports + classifier.genUsageImports
-	}
-
-
-	def public static genRelativeNamedImport(Element element) '''
+	def public static genBodyIncludes(Classifier classifier) '''
+		««« Includes from <<Include>> stereotype's preBody attribute
+		«CIncludePreBody(classifier)»
+		««« Include self header
+		// Include self header
+		«includeDirective(classifier.name + '.' + CCodeGenUtils.getHeaderSuffix())»
+		««« Derived includes from required classifiers that are dependencies and pointers
+		// Derived includes
+		«FOR path : CClassAllIncludesBody(classifier).sort» 
+			«includeDirective(path)»
+		«ENDFOR»
+		««« Includes from <<Include>> stereotype's body attribute
+		«CIncludeBody(classifier)»
 	'''
 
-
-	def public static genRelativeNamedImport(NamedElement namedElement1, NamedElement namedElement2) '''
-		«IF (namedElement1.hasStereotypeTree(ModelLibrary))»
-			#include <«namedElement1.namespace.genName()».h>
-		«ELSE»
-			#include "«namedElement2.getRelativePath(namedElement1)»«namedElement1.genName()».h"
-		«ENDIF»
-	'''
-
-	def public static genRelativeNamedImport(Package pkg, NamedElement namedElement) '''
-		«IF (pkg.hasStereotypeTree(ModelLibrary))»
-			#include <«pkg.genName()».h>
-		«ELSE»
-			#include "«pkg.getRelativePath(namedElement)»«pkg.genName».h"
-		«ENDIF»
-	'''
-
-
-	def public static genOwningPackageImports(Classifier classifier) {
-		classifier.namespace.genNamespaceImports()
-	}
-
-
-	def public static genNamespaceImports(Namespace namespace) {
-		namespace.elementImports.map[it.importedElement]
-	}
-
-	def public static genUsageImports(Classifier lassifier) {
-		return new ArrayList<Classifier>();
-	}
-
-	def public static genUsageImports(Class clazz) {
-		if (clazz.hasStereotypeTree(ModelLibrary)) {
-			clazz.getUsedInterfaces()
-		}
-		else {
-			clazz.getUsedInterfaces().map[getInterfaceRealizationClass]
-		}
-	}
-
-	def public static getTypeListOfClassifier(Class clazz) {
-		val list = clazz.getAllAttributes.map[type]
-		list.addAll(clazz.getAllOperations.map[ownedParameters.map[type]])
-		list.addAll(clazz.generals)
-		return list
-	}
-
-
-	def public static getTypeListOfClassifier(Interface intf) {
-		val list = intf.ownedAttributes.map[type]
-		list.addAll(intf.ownedOperations.map[ownedParameters.map[type]])
-		list.addAll(intf.generals)
-		return list
-	}
-
-
-	def public static getTypeListOfClassifier(DataType dataType) {
-		val list = dataType.ownedAttributes.map[type]
-		list.addAll(dataType.ownedOperations.map[ownedParameters.map[type]])
-		list.addAll(dataType.generals)
-		return list
-	}
-
-	// TODO: why do need stdlib in this case? 
-	def public static genDynamicInstanciationImport(Classifier classifier) '''
+	// TODO: why do need stdlib in this case?
+	// TODO: why do we need this at all? 
+	def public static genStdInclude() '''
 		#include <stdio.h>
 		#include <stdlib.h>
 	'''
+
+	static def includeDirective(String path) {
+		if ((path !== null) && (path.length > 0))
+			return '''#include ''' + '"' + path + '"'
+	}
+	
+	static def CClassAllIncludesHeader(Classifier clazz) {
+		cClassAllIncludes(clazz, CClassUtils.includedClassifiers(clazz))
+	}
+
+	static def CClassAllIncludesBody(Classifier classifier) {
+		cClassAllIncludes(classifier, CClassUtils.includedImplementationClassifiers(classifier))
+	}
+
+	static def cClassAllIncludes(Classifier classifier, EList<Classifier> list) {
+		var List<String> newList = new ArrayList<String>()
+		for (cl : list) {
+			//var String str = null
+			if (cl != classifier && !GenUtils.hasStereotype(cl, NoCodeGen) || GenUtils.hasStereotype(cl, External)) {
+				if ((cl instanceof Enumeration || cl instanceof PrimitiveType) &&
+					!GenUtils.hasStereotype(cl, External) &&
+					!GenUtils.hasStereotypeTree(cl, ExternLibrary)) {
+					if (cl.owner instanceof Package && cl.owner != classifier.owner) {
+						/*
+						 * No additional include is required, if enum and primitive types are in
+						 * the same package. The latter is always included.
+						 */
+						// TODO how is it done in C compared to C++? Following is from C++ generator.
+						//var includePath = (cl.owner as Package).cOwnerPackageIncludePath
+						//if (!newList.contains(includePath)) newList.add(includePath)
+					} else {
+						// str = null
+					}
+				} else {
+					for (includePath : importScript.cClassIncludes(cl)) {
+						if (!newList.contains(includePath)) newList.add(includePath)
+					}
+				}
+			} else {
+				//str = null
+			}
+		}
+		return newList.filter[str | str != null]
+	}
+
+ 	static def cOwnerPackageIncludePath(Package pkg) {
+		if ((pkg != null) && (!GenUtils.hasStereotype(pkg, CppRoot))) {
+			return GenUtils.getFullPath(pkg) + '/Pkg_' + pkg.name + '.h'
+		} else {
+			return null
+		}
+	}
+
+	static def cClassIncludes(NamedElement ne) {
+		var List<String> result = new ArrayList<String>()
+		if (GenUtils.hasStereotypeTree(ne, ExternLibrary)) {
+			// If a class is in an external library, use #include
+			// directives defined there
+			result.addAll(GenUtils.getApplicationTree(ne, ExternLibrary).includes)
+			// No individual includes are produced for members
+			// unless the stereotype "External" defines one explicitly
+			if (GenUtils.hasStereotype(ne, External)) {
+				val incPath = includeName(ne)
+				if (incPath !== null) {
+					result.add(incPath)
+				}
+				// else: if unset, assume that no additional include directive is required
+			}
+		} else {
+			result.add(includeName(ne))
+		}
+		return result
+	}
+
+	static def includeName(NamedElement ne) {
+		if (GenUtils.hasStereotypeTree(ne, Template)) {
+			return UMLUtil.getStereotypeApplication(ne, Template).declaration
+		} else {
+			if (GenUtils.hasStereotypeTree(ne, External)) {
+				return UMLUtil.getStereotypeApplication(ne, External).incPath
+			} else {
+				// standard case (no stereotypes are applied)
+				return ne.name + '.' + CCodeGenUtils.getHeaderSuffix()
+			}
+		}
+	}
+
+	static def declareDirective(String path) {
+		if ((path != null) && (path.length > 0)) {
+			return path
+		}	
+	}
+
+	static def CClassAllDeclares(Classifier clazz) {
+		importScript.cClassAllDeclares(clazz, CClassUtils.declaredClassifiers(clazz), CClassUtils.includedClassifiers(clazz))
+	}
+
+	static def cClassAllDeclares(Classifier classifier, EList<Classifier> declaredClassifiers, EList<Classifier> includedClassifiers) {
+		var List<String> newList = new ArrayList<String>()
+		
+		if (declaredClassifiers != null) {
+			if (includedClassifiers != null) {
+				declaredClassifiers.removeAll(includedClassifiers)
+			}
+			
+			for (cl : declaredClassifiers) {
+				if (cl != classifier && !GenUtils.hasStereotype(cl, NoCodeGen) || GenUtils.hasStereotype(cl, External)) {
+					var declaration = "";
+					
+					if (!(cl instanceof Enumeration) && !(cl instanceof PrimitiveType)) {
+						declaration = "struct " + cl.name + ";";
+					}
+					
+					if (declaration != "") {
+						if (!newList.contains(declaration)) {
+							newList.add(declaration);
+						}
+					}
+				}
+			}
+		}
+		
+		return newList.filter[str | str != null]
+	}
+	
+	static def CIncludeHeader(NamedElement ne) {
+		if (GenUtils.hasStereotype(ne, Include)) {
+			UMLUtil.getStereotypeApplication(ne, Include)
+			var header = UMLUtil.getStereotypeApplication(ne, Include).header
+			if ((header !== null) && (header.length > 0)) {
+				var includeHeader = constIncludeHeaderStart + GenUtils.cleanCR(header) + '\n' +
+					constIncludeHeaderEnd
+				return includeHeader
+			}
+		}
+	}
+
+	static def constIncludeHeaderStart() '''
+		// Include from Include stereotype (header)
+	'''
+
+	static def constIncludeHeaderEnd() '''
+		// End of Include stereotype (header)
+	'''
+
+	static def CIncludePreBody(NamedElement ne) {
+		if (GenUtils.hasStereotype(ne, Include)) {
+			var String preBody = UMLUtil.getStereotypeApplication(ne, Include).preBody
+			if ((preBody != null) && (preBody.length > 0)) {
+				var includePreBody = constIncludePreBodyStart + GenUtils.cleanCR(preBody) + '\n' +
+					constIncludePreBodyEnd
+				return includePreBody
+			}
+		}
+	}
+
+	static def constIncludePreBodyStart() '''
+		// Include from Include stereotype (preBody)
+	'''
+
+	static def constIncludePreBodyEnd() '''
+		// End of Include from Include stereotype (preBody)
+	'''
+
+	static def CIncludeBody(NamedElement ne) {
+		if (GenUtils.hasStereotype(ne, Include)) {
+			var String body = UMLUtil.getStereotypeApplication(ne, Include).body
+			if ((body != null) && (body.length > 0)) {
+				var includeBody = constIncludeBodyStart + GenUtils.cleanCR(body) + '\n' +
+					constIncludeBodyEnd
+				return includeBody
+			}
+		}
+	}
+	
+	static def constIncludeBodyStart() '''
+		// Include from Include stereotype (body)
+	'''
+
+	static def constIncludeBodyEnd() '''
+		// End of Include from Include stereotype (body)
+	'''
 }
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/module/classModuleScript.xtend b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/module/classModuleScript.xtend
index e0c360d..4d1cdb4 100644
--- a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/module/classModuleScript.xtend
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/module/classModuleScript.xtend
@@ -11,34 +11,29 @@
 
 package org.eclipse.papyrus.designer.languages.c.codegen.module
 
+import org.eclipse.papyrus.designer.languages.c.codegen.lib.TransformationUtil
+import org.eclipse.uml2.uml.CallEvent
 import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.FinalState
+import org.eclipse.uml2.uml.SignalEvent
+import org.eclipse.uml2.uml.State
+import org.eclipse.uml2.uml.StateMachine
 import org.eclipse.uml2.uml.VisibilityKind
 
 import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.classScript.*
 import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.commonScript.*
 import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.functionScript.*
+import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.importScript.*
 import static extension org.eclipse.papyrus.designer.languages.c.codegen.lib.variableScript.*
 import static extension org.eclipse.papyrus.designer.languages.c.codegen.services.UmlCommentServices.*
-import org.eclipse.uml2.uml.CallEvent
-import org.eclipse.uml2.uml.SignalEvent
-import org.eclipse.uml2.uml.Trigger
-import org.eclipse.uml2.uml.StateMachine
-import org.eclipse.papyrus.designer.languages.c.codegen.lib.TransformationUtil
-import org.eclipse.uml2.uml.State
-import org.eclipse.uml2.uml.FinalState
 
 class classModuleScript {
 	def static classModuleScript(Class clazz) '''
-		// This template is called by the main module file 
+		««« This template is called by the main module file 
 		«clazz.genHeading()»
 		
-		// include of the self header
-		«clazz.genIncludeSelf()»
-		
-		//  Generate import of class ---------------------------------------------
-		/* "startUserCode" to add imports */
-		/* "endUserCode"   to add imports */
-		
+		«clazz.genBodyIncludes»
+
 		«clazz.genModuleDeclarationBody()»
 		«clazz.genModuleImplementationBody()»
 	'''
@@ -125,32 +120,28 @@
 			«ENDFOR»
 		«ENDIF»
 		
-		
 		«IF (clazz.classifierBehavior != null && !clazz.ownedBehaviors.filter(StateMachine).isEmpty)»
-		«var sm = clazz.ownedBehaviors.filter(StateMachine).head»
-		// ----------------------------------Entry Exit and DoActivity Implementations for each state ----------------------------------
-				«IF sm.regions.head.subvertices.filter(State).filter[!(it instanceof FinalState)].isEmpty»
-						«var states = clazz.ownedBehaviors.filter(StateMachine).head.regions.head.subvertices.filter(State).filter[!(it instanceof FinalState)]»
-								«FOR state : states»		
-									«IF (TransformationUtil.isBehaviorExist(state.entry))»
-										«state.genEntryImplementation»
-									«ENDIF»
-									«IF (TransformationUtil.isBehaviorExist(state.exit))»
-										«state.genExitImplementation»
-									«ENDIF»
-									«IF (TransformationUtil.isBehaviorExist(state.doActivity))»
-										«state.genDoActivityImplementation»
-									«ENDIF»
-									«ENDFOR»
-										
-				«ENDIF»
-				«IF(TransformationUtil.hasTriggerlessTransition(sm))»
-		//--------------------process Completion Event for completion transition-------------------//
-					«clazz.genProcessCompletionEventFunctionImplementation»
-					
-				«ENDIF»
-				
+			«var sm = clazz.ownedBehaviors.filter(StateMachine).head»
+			// ----------------------------------Entry Exit and DoActivity Implementations for each state ----------------------------------
+			«IF sm.regions.head.subvertices.filter(State).filter[!(it instanceof FinalState)].isEmpty»
+					«var states = clazz.ownedBehaviors.filter(StateMachine).head.regions.head.subvertices.filter(State).filter[!(it instanceof FinalState)]»
+							«FOR state : states»		
+								«IF (TransformationUtil.isBehaviorExist(state.entry))»
+									«state.genEntryImplementation»
+								«ENDIF»
+								«IF (TransformationUtil.isBehaviorExist(state.exit))»
+									«state.genExitImplementation»
+								«ENDIF»
+								«IF (TransformationUtil.isBehaviorExist(state.doActivity))»
+									«state.genDoActivityImplementation»
+								«ENDIF»
+								«ENDFOR»
+									
+			«ENDIF»
+			«IF(TransformationUtil.hasTriggerlessTransition(sm))»
+				//--------------------process Completion Event for completion transition-------------------//
+				«clazz.genProcessCompletionEventFunctionImplementation»
+			«ENDIF»
 		«ENDIF»
-		
 	'''
 }
diff --git a/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/services/CClassUtils.java b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/services/CClassUtils.java
new file mode 100644
index 0000000..9e4c625
--- /dev/null
+++ b/languages/c/org.eclipse.papyrus.designer.languages.c.codegen/src/org/eclipse/papyrus/designer/languages/c/codegen/services/CClassUtils.java
@@ -0,0 +1,214 @@
+/*******************************************************************************

+ * Copyright (c) 2006 - 2012, 2017 CEA LIST.

+ * All rights reserved. This program and the accompanying materials

+ * are made available under the terms of the Eclipse Public License v1.0

+ * which accompanies this distribution, and is available at

+ * http://www.eclipse.org/legal/epl-v10.html

+ *

+ * Contributors:

+ *     Shuai Li (CEA LIST) <shuai.li@cea.fr> - Initial API and implementation

+ *******************************************************************************/

+

+package org.eclipse.papyrus.designer.languages.c.codegen.services;

+

+import java.util.List;

+

+import org.eclipse.emf.common.util.BasicEList;

+import org.eclipse.emf.common.util.EList;

+import org.eclipse.emf.common.util.UniqueEList;

+import org.eclipse.emf.ecore.EObject;

+import org.eclipse.papyrus.designer.languages.common.base.GenUtils;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.ExternLibrary;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.External;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Inline;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.NoCodeGen;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Ptr;

+import org.eclipse.papyrus.designer.languages.cpp.profile.C_Cpp.Ref;

+import org.eclipse.uml2.uml.Classifier;

+import org.eclipse.uml2.uml.Enumeration;

+import org.eclipse.uml2.uml.Interface;

+import org.eclipse.uml2.uml.Package;

+import org.eclipse.uml2.uml.PrimitiveType;

+import org.eclipse.uml2.uml.util.UMLUtil;

+

+public class CClassUtils {

+	/**

+	 * Calculate the list of classifiers that needs to be included in a header file

+	 *

+	 * @param currentClass

+	 * @return

+	 */

+	public static EList<Classifier> includedClassifiers(Classifier currentClass) {

+		// Retrieve package used by current package (dependencies)

+		// use a unique list to avoid duplicates

+		EList<Classifier> usedClasses = new UniqueEList<Classifier>();

+

+		// Lists of excluded/included stereotypes

+		EList<Class<? extends EObject>> ptrRefStereotypes = new BasicEList<Class<? extends EObject>>();

+		ptrRefStereotypes.add(Ptr.class);

+		ptrRefStereotypes.add(Ref.class);

+		

+		EList<Class<? extends EObject>> noCodeGenInlineStereotypes = new BasicEList<Class<? extends EObject>>();

+		noCodeGenInlineStereotypes.add(NoCodeGen.class);

+		noCodeGenInlineStereotypes.add(Inline.class);

+		

+		EList<Class<? extends EObject>> inlineStereotypes = new BasicEList<Class<? extends EObject>>();

+		inlineStereotypes.add(Inline.class);

+		

+		EList<Class<? extends EObject>> noCodeGenStereotypes = new BasicEList<Class<? extends EObject>>();

+		noCodeGenStereotypes.add(NoCodeGen.class);

+		

+		// class attributes dependencies (non-ptr and non-ref)

+		usedClasses.addAll(GenUtils.getTypesViaAttributes(currentClass, ptrRefStereotypes, null, true, true));

+		addEnumerationsPrimitiveTypesExternalTypes(usedClasses, GenUtils.getTypesViaAttributes(currentClass));

+		

+		// class inline operation parameters dependencies (non-ptr and non-ref)

+		usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true));

+		addEnumerationsPrimitiveTypesExternalTypes(usedClasses, GenUtils.getTypesViaOperations(currentClass));

+		

+		// inner classifier attribute dependencies (non-ptr and non-ref)

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaAttributes(currentClass, ptrRefStereotypes, null, true, true));

+		addEnumerationsPrimitiveTypesExternalTypes(usedClasses, GenUtils.getInnerClassifierTypesViaAttributes(currentClass));

+		

+		// inner classifier operation parameters dependencies (non-ptr and non-ref)

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true));

+		addEnumerationsPrimitiveTypesExternalTypes(usedClasses, GenUtils.getInnerClassifierTypesViaOperations(currentClass));

+		

+		// realized interface dependencies

+		if (currentClass instanceof org.eclipse.uml2.uml.Class) {

+			org.eclipse.uml2.uml.Class clazz = (org.eclipse.uml2.uml.Class) currentClass;

+			EList<Interface> implementedInterfaces = clazz.getImplementedInterfaces();

+			usedClasses.addAll(implementedInterfaces);

+		}

+		// dependencies and associations

+		usedClasses.addAll(GenUtils.getTypesViaRelationshipsNoDeps(currentClass));

+

+		// template parameters are declared locally (if owned) and do not correspond to a file

+		// that can be included

+		usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass));

+		return usedClasses;

+	}

+	

+	/**

+	 * Calculate the list of classifiers that needs to be included in a body file

+	 *

+	 * @param currentClass

+	 * @return

+	 */

+	public static EList<Classifier> includedImplementationClassifiers(Classifier currentClass) {

+		// Retrieve package used by current package (dependencies)

+		// use a unique list to avoid duplicates

+		EList<Classifier> usedClasses = new UniqueEList<Classifier>();

+

+		// Include all declared classifiers in header

+		// Make sure to not include classifiers already included in header

+		usedClasses.addAll(declaredClassifiers(currentClass));

+		usedClasses.removeAll(includedClassifiers(currentClass));

+		

+		// dependency relationships

+		usedClasses.addAll(GenUtils.getTypesViaDependencies(currentClass));

+		

+		// template parameters are declared locally (if owned) and do not correspond to a file

+		// that can be included

+		usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass));

+		return usedClasses;

+	}

+	

+	/**

+	 * Calculate the list of classifiers that needs to be declared in a header file

+	 *

+	 * @param currentClass

+	 * @return

+	 */

+	public static EList<Classifier> declaredClassifiers(Classifier currentClass) {

+		EList<Classifier> usedClasses = new UniqueEList<Classifier>();

+

+		// List of excluded/included stereotypes

+		EList<Class<? extends EObject>> ptrRefStereotypes = new BasicEList<Class<? extends EObject>>();

+		ptrRefStereotypes.add(Ptr.class);

+		ptrRefStereotypes.add(Ref.class);

+		

+		EList<Class<? extends EObject>> inlineStereotypes = new BasicEList<Class<? extends EObject>>();

+		inlineStereotypes.add(Inline.class);

+		

+		EList<Class<? extends EObject>> noCodeGenStereotypes = new BasicEList<Class<? extends EObject>>();

+		noCodeGenStereotypes.add(NoCodeGen.class);

+		

+		// class attributes dependencies (only ptr and ref and shared aggregation)

+		usedClasses.addAll(GenUtils.getTypesViaAttributes(currentClass, null, ptrRefStereotypes, false, false));

+		usedClasses.addAll(GenUtils.getTypesViaSharedAggregationAttributes(currentClass));

+		// operation parameters dependencies

+		usedClasses.addAll(GenUtils.getTypesViaOperations(currentClass));

+		usedClasses.removeAll(GenUtils.getTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true)); // Remove inline operation parameter types that have been included previously

+		// no-specification opaque behavior dependencies

+		usedClasses.addAll(GenUtils.getTypesViaOpaqueBehaviors(currentClass));

+		

+		// inner classifier attribute dependencies (only ptr and ref and shared aggregation)

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaAttributes(currentClass, null, ptrRefStereotypes, false, false));

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaSharedAggregationAttributes(currentClass));

+		// inner classifier parameters dependencies

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass));

+		usedClasses.removeAll(GenUtils.getInnerClassifierTypesViaOperations(currentClass, noCodeGenStereotypes, inlineStereotypes, ptrRefStereotypes, null, true)); // Remove inner classifier inline operation parameter types that have been included previously

+		// inner classifier no-specification opaque behavior dependencies

+		usedClasses.addAll(GenUtils.getInnerClassifierTypesViaOpaqueBehaviors(currentClass));

+		

+		// TODO inline operation body dependencies: how?

+		

+		// template parameters are declared locally (if owned) and do not correspond to a file

+		// that can be included

+		usedClasses.removeAll(GenUtils.getTemplateParameteredElements(currentClass));

+		

+		// Remove enumerations and primitive types

+		List<Classifier> enumerationsAndPrimitiveTypes = new UniqueEList<Classifier>();

+		for (Classifier classifier : usedClasses) {

+			if ((classifier instanceof Enumeration) || (classifier instanceof PrimitiveType)) {

+				if (classifier.getOwner() instanceof Package) {

+					enumerationsAndPrimitiveTypes.add(classifier);

+				}

+			}

+		}

+		usedClasses.removeAll(enumerationsAndPrimitiveTypes);

+		

+		return usedClasses;

+	}

+	

+	public static EList<Classifier> usingClassifiers(Classifier currentClass) {

+		EList<Classifier> usedClasses = new UniqueEList<Classifier>();

+		usedClasses.addAll(includedClassifiers(currentClass));

+		usedClasses.addAll(includedImplementationClassifiers(currentClass));

+		usedClasses.addAll(declaredClassifiers(currentClass));

+		

+		EList<Classifier> classesToRemove = new UniqueEList<Classifier>();

+		for (Classifier classifier : usedClasses) {

+			if (classifier.getOwner() instanceof Classifier) {

+				classesToRemove.add(classifier);

+			} else if (!classifier.getModel().equals(currentClass.getModel())) {

+				classesToRemove.add(classifier);

+			} else if (UMLUtil.getStereotypeApplication(classifier, External.class) != null)  {

+				classesToRemove.add(classifier);

+			} else if (classifier.getOwner() instanceof Package

+					&& UMLUtil.getStereotypeApplication(classifier.getOwner(), ExternLibrary.class) != null) {

+				classesToRemove.add(classifier);

+			}

+		}

+		

+		usedClasses.removeAll(classesToRemove);

+		

+		return usedClasses;

+	}

+

+	private static void addEnumerationsPrimitiveTypesExternalTypes(List<Classifier> usedClasses, List<Classifier> unfilteredClasses) {

+		if (usedClasses != null && unfilteredClasses != null) {

+			for (Classifier classifier : unfilteredClasses) {

+				if ((classifier instanceof Enumeration) || (classifier instanceof PrimitiveType)) {

+					if (classifier.getOwner() instanceof Package) {

+						usedClasses.add(classifier);

+					}

+				} else if (GenUtils.hasStereotype(classifier, External.class)) {

+					usedClasses.add(classifier);

+				}

+			}

+		}

+		

+	}

+}