Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core')
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java60
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/HelloWorldModelWizard.java27
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/ProducerConsumerModelWizard.java27
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindCppIncludeToFirstActual.java73
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindOperation.java54
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/InstantiateCppIncludeWithItSelf.java74
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java130
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/embeddingrules/AccordCall.java95
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java68
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java61
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIcallback.java162
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIpoll.java161
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort.java132
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort2.java138
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ProvideInterface.java37
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PullConsumer.java162
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushConsumer.java110
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProdPullCons.java75
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProducer.java130
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/TemplatePort.java183
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseConjIntf.java187
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseInterface.java42
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AMIPull.xtend34
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AsyncCalls.xtend57
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/BehaviorUtil.java111
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/CppUtils.xtend81
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/FIFO.xtend13
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/GlobalConstants.xtend56
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/Marshalling.xtend51
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/MultipleReceptacle.xtend14
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineGen.xtend412
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineUtil.java260
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StructBasedMarshalling.xtend25
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/SyncCalls.xtend13
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLAction.xtend58
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLChain.xtend91
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlatModel2Cpp.xtend667
-rw-r--r--extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlattener.xtend556
38 files changed, 4687 insertions, 0 deletions
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java
new file mode 100644
index 00000000000..8859e978d40
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java
@@ -0,0 +1,60 @@
+package org.eclipse.papyrus.qompass.modellibs.core;
+
+import org.eclipse.papyrus.infra.core.log.LogHelper;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.papyrus.qompass.modellibs.core"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ public static LogHelper log;
+
+ /**
+ * The constructor
+ */
+ public Activator() {
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+
+ // register the login helper
+ log = new LogHelper(plugin);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/HelloWorldModelWizard.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/HelloWorldModelWizard.java
new file mode 100644
index 00000000000..5972200b5ff
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/HelloWorldModelWizard.java
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core;
+
+import org.eclipse.papyrus.uml.diagram.wizards.ModelCopyWizard;
+
+/**
+ * Copy wizard for the HelloWorld example
+ */
+public class HelloWorldModelWizard extends ModelCopyWizard {
+
+ public HelloWorldModelWizard() {
+ super("HelloWorld"); //$NON-NLS-1$
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/ProducerConsumerModelWizard.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/ProducerConsumerModelWizard.java
new file mode 100644
index 00000000000..38ae39a4204
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/ProducerConsumerModelWizard.java
@@ -0,0 +1,27 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core;
+
+import org.eclipse.papyrus.uml.diagram.wizards.ModelCopyWizard;
+
+/**
+ * Copy wizard for the ProducerConsumer example
+ */
+public class ProducerConsumerModelWizard extends ModelCopyWizard {
+
+ public ProducerConsumerModelWizard() {
+ super("ProducerConsumer"); //$NON-NLS-1$
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindCppIncludeToFirstActual.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindCppIncludeToFirstActual.java
new file mode 100644
index 00000000000..a8e25cbbf12
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindCppIncludeToFirstActual.java
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.C_Cpp.Include;
+import org.eclipse.papyrus.FCM.util.IBindingHelper;
+import org.eclipse.papyrus.qompass.designer.core.listeners.PostCopyListener;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TextTemplateBinding;
+import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+/**
+ * Instantiate (bind Acceleo template) the text within a C++Include stereotype.
+ *
+ * The actual is the first actual within the template binding. This function does not check
+ * whether the classifier has the template stereotype.
+ *
+ * Note: this function is C++ specific, but many parts of the model library are C++ specific as well
+ *
+ */
+public class BindCppIncludeToFirstActual implements PostCopyListener, IBindingHelper {
+
+ @Override
+ public void postCopyEObject(LazyCopier copy, EObject targetEObj) {
+ // if (copy.get(sourceEObj) isWithinTemplate)
+ if (targetEObj instanceof Classifier) {
+
+ Classifier targetCl = (Classifier) targetEObj;
+ try {
+ Classifier actual = TemplateUtils.getFirstActualFromBinding(binding);
+ Include cppInclude = UMLUtil.getStereotypeApplication(targetCl, Include.class);
+ if ((actual != null) && (cppInclude != null)) {
+ TransformationContext.classifier = targetCl;
+ String newBody = TextTemplateBinding.bind(cppInclude.getBody(), actual, null);
+ String newPreBody = TextTemplateBinding.bind(cppInclude.getPreBody(), actual, null);
+ String newHeader = TextTemplateBinding.bind(cppInclude.getHeader(), actual, null);
+ cppInclude.setBody(newBody);
+ cppInclude.setPreBody(newPreBody);
+ cppInclude.setHeader(newHeader);
+ }
+ } catch (TransformationException e) {
+ // create nested exception
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ protected TemplateBinding binding;
+
+ @Override
+ public void handleElement(TemplateBinding binding, Element object) {
+ this.binding = binding;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindOperation.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindOperation.java
new file mode 100644
index 00000000000..6b2d352e1ee
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/BindOperation.java
@@ -0,0 +1,54 @@
+package org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.FCM.util.IBindingHelper;
+import org.eclipse.papyrus.qompass.designer.core.listeners.PreCopyListener;
+import org.eclipse.papyrus.qompass.designer.core.templates.BindingUtils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils;
+import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException;
+import org.eclipse.papyrus.qompass.modellibs.core.Activator;
+import org.eclipse.uml2.uml.Behavior;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.OpaqueBehavior;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.TemplateBinding;
+
+/**
+ * Bind an operation to an actual, i.e. evaluate the Acceleo template within the opaque behavior associated with
+ * the operation.
+ */
+public class BindOperation implements IBindingHelper, PreCopyListener {
+
+ private TemplateBinding binding;
+
+ @Override
+ public EObject preCopyEObject(LazyCopier copy, EObject sourceEObj) {
+
+ if (sourceEObj instanceof Operation) {
+ Operation operation = (Operation) sourceEObj;
+ Classifier actual = TemplateUtils.getFirstActualFromBinding(binding);
+
+ Operation newOperation = BindingUtils.instantiateOperation(copy, actual, operation);
+ for (Behavior method : operation.getMethods()) {
+ if (method instanceof OpaqueBehavior) {
+ try {
+ Behavior newBehavior =
+ BindingUtils.instantiateBehavior(copy, actual, (OpaqueBehavior) method);
+ newBehavior.setSpecification(newOperation);
+ } catch (TransformationException e) {
+ Activator.log.error(e);
+ }
+ }
+ }
+ return newOperation;
+ }
+ return sourceEObj;
+ }
+
+ @Override
+ public void handleElement(TemplateBinding binding, Element object) {
+ this.binding = binding;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/InstantiateCppIncludeWithItSelf.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/InstantiateCppIncludeWithItSelf.java
new file mode 100644
index 00000000000..cd4a730ee30
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/InstantiateCppIncludeWithItSelf.java
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.C_Cpp.Include;
+import org.eclipse.papyrus.FCM.Template;
+import org.eclipse.papyrus.FCM.util.IBindingHelper;
+import org.eclipse.papyrus.qompass.designer.core.listeners.PostCopyListener;
+import org.eclipse.papyrus.qompass.designer.core.templates.TextTemplateBinding;
+import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+/**
+ * Instantiate (bind Acceleo template) the text within a C++Include stereotype.
+ *
+ * Difference to InstantiateCppInclude: This function does not obtain the actual from a template
+ * binding. Instead it takes the classifier having the Template stereotype as actual.
+ * TODO: What's the use of this function. The classifier is known at this time - unless in a template?
+ *
+ * Note: this function is C++ specific, but many parts of the model library are C++ specific as well
+ *
+ */
+@Deprecated
+public class InstantiateCppIncludeWithItSelf implements PostCopyListener, IBindingHelper {
+
+ @Override
+ public void postCopyEObject(LazyCopier copy, EObject targetEObj) {
+ // if (copy.get(sourceEObj) isWithinTemplate)
+ if (targetEObj instanceof Classifier) {
+ // TODO: C++ specific code!
+ Classifier targetCl = (Classifier) targetEObj;
+ Template template = UMLUtil.getStereotypeApplication(targetCl, Template.class);
+ // apply, in case of pass-classifier
+ if ((template != null) && (template.getHelper() == null)) {
+ try {
+ Include cppInclude = UMLUtil.getStereotypeApplication(targetCl, Include.class);
+ TransformationContext.classifier = targetCl;
+ String newBody = TextTemplateBinding.bind(cppInclude.getBody(), targetCl, null);
+ String newPreBody = TextTemplateBinding.bind(cppInclude.getPreBody(), targetCl, null);
+ String newHeader = TextTemplateBinding.bind(cppInclude.getHeader(), targetCl, null);
+ cppInclude.setBody(newBody);
+ cppInclude.setPreBody(newPreBody);
+ cppInclude.setHeader(newHeader);
+ } catch (TransformationException e) {
+ // create nested exception
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void handleElement(TemplateBinding binding, Element object) {
+ // don't need to handle binding
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java
new file mode 100644
index 00000000000..996363af3dd
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java
@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.papyrus.FCM.util.IBindingHelper;
+import org.eclipse.papyrus.qompass.designer.core.listeners.PreCopyListener;
+import org.eclipse.papyrus.qompass.designer.core.templates.BindingUtils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TextTemplateBinding;
+import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException;
+import org.eclipse.papyrus.qompass.modellibs.core.Activator;
+import org.eclipse.uml2.uml.Behavior;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Element;
+import org.eclipse.uml2.uml.EnumerationLiteral;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.OpaqueBehavior;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * This binding helper loops over all operations of the actual template parameter
+ * (typically an interface)
+ *
+ */
+public class LoopOperations implements IBindingHelper, PreCopyListener {
+
+ private TemplateBinding binding;
+
+ @Override
+ public EObject preCopyEObject(LazyCopier copy, EObject sourceEObj) {
+
+ if (sourceEObj instanceof Operation) {
+ Operation operation = (Operation) sourceEObj;
+
+ Classifier actual = TemplateUtils.getFirstActualFromBinding(binding);
+
+ if (!(actual instanceof Interface)) {
+ return sourceEObj;
+ }
+ Interface passedActualIntf = (Interface) actual;
+ Operation last = null;
+ EList<Element> removalList = new BasicEList<Element>();
+ for (Operation intfOperation : passedActualIntf.getAllOperations()) {
+ for (Element removalElement : removalList) {
+ copy.removeForCopy(removalElement); // enable subsequent instantiations
+ }
+ removalList.clear();
+ last = BindingUtils.instantiateOperation(copy, intfOperation, operation);
+ removalList.add(operation);
+ for (Behavior method : operation.getMethods()) {
+ if (method instanceof OpaqueBehavior) {
+ try {
+ Behavior newBehavior =
+ BindingUtils.instantiateBehavior(copy, intfOperation, (OpaqueBehavior) method);
+ newBehavior.setSpecification(last);
+ } catch (TransformationException e) {
+ Activator.log.error(e);
+ ;
+ }
+ // removalList.add(method);
+ copy.removeForCopy(method); // enable subsequent instantiations
+ }
+ }
+ }
+ // from a logical viewpoint, we need to copy parameters & name, but not the
+ // operation identity.
+ copy.put(operation, last);
+ return last;
+ /*
+ * else { // not LOOP_OPERATIONS
+ * Operation newOperation = instantiateOperation(actual, template, operation, boundClass);
+ * for(Behavior method : operation.getMethods()) {
+ * if(method instanceof OpaqueBehavior) {
+ * Behavior newBehavior =
+ * instantiateBehavior(actual, template, (OpaqueBehavior)method);
+ * newBehavior.setSpecification(newOperation);
+ * }
+ * }
+ * return newOperation;
+ */
+ }
+ else if (sourceEObj instanceof EnumerationLiteral) {
+ EnumerationLiteral literal = (EnumerationLiteral) sourceEObj;
+ Classifier actual = TemplateUtils.getFirstActualFromBinding(binding);
+ // Type passedActual = getPassedActual(template, actual, boundClass);
+ Type passedActual = actual;
+ if (!(passedActual instanceof Interface)) {
+ return sourceEObj;
+ }
+ Interface passedActualIntf = (Interface) passedActual;
+ EnumerationLiteral newLiteral = null;
+ for (Operation intfOperation : passedActualIntf.getAllOperations()) {
+ copy.removeForCopy(literal);
+ newLiteral = copy.getCopy(literal);
+ try {
+ String newName = TextTemplateBinding.bind(literal.getName(), intfOperation, null);
+ newLiteral.setName(newName);
+ } catch (TransformationException e) {
+ Activator.log.error(e);
+ newLiteral.setName("none"); //$NON-NLS-1$
+ }
+ }
+ return newLiteral;
+ }
+ return null;
+ }
+
+ @Override
+ public void handleElement(TemplateBinding binding, Element object) {
+ this.binding = binding;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/embeddingrules/AccordCall.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/embeddingrules/AccordCall.java
new file mode 100644
index 00000000000..e76e284f645
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/embeddingrules/AccordCall.java
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.embeddingrules;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.papyrus.FCM.Connector;
+import org.eclipse.papyrus.FCM.util.ConnectorTypeUtil;
+import org.eclipse.papyrus.FCM.util.FCMUtil;
+import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
+import org.eclipse.uml2.uml.ConnectableElement;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+/**
+ * Embedding rule
+ * TODO: currently unused
+ *
+ */
+// @unused
+public class AccordCall extends ConnectorTypeUtil {
+
+ private ConnectableElement clientRole = null;
+ private ConnectableElement serverRole = null;
+ private ConnectableElement rtuRole = null;
+ private ConnectableElement connectorRole = null;
+
+ @Override
+ public FCMUtil.RoleBindingTable getRoleBindings(Connector connector) {
+ super.getRoleBindings(connector);
+
+ clientRole = bindingTable.getRoleKeyByName("client");
+ serverRole = bindingTable.getRoleKeyByName("server");
+ rtuRole = bindingTable.getRoleKeyByName("rtu");
+ connectorRole = bindingTable.getRoleKeyByName("connector");
+
+ for (org.eclipse.uml2.uml.ConnectorEnd end : connector.getBase_Connector().getEnds()) {
+ if (end.getRole() instanceof org.eclipse.uml2.uml.Port) {
+ org.eclipse.uml2.uml.Port port = (org.eclipse.uml2.uml.Port) end.getRole();
+ org.eclipse.uml2.uml.Property part = end.getPartWithPort();
+ if (StereotypeUtil.isApplied(port, org.eclipse.papyrus.FCM.Port.class)) {
+ org.eclipse.papyrus.FCM.Port fcmPort = UMLUtil.getStereotypeApplication(port, org.eclipse.papyrus.FCM.Port.class);
+ if (fcmPort.getKind().getBase_Class().getName().equals("UseInterfaceWithRtf")) {
+ // => elements associated with the connector end play the client role
+ List<NamedElement> clientActors = new ArrayList<NamedElement>();
+ clientActors.add(port);
+ clientActors.add(part);
+ bindingTable.addEntry(clientRole, clientActors);
+ }
+ else if (fcmPort.getKind().getBase_Class().getName().equals("ProvideInterface")) {
+ // => elements associated with the connector end play the server role
+ List<NamedElement> serverActors = new ArrayList<NamedElement>();
+ serverActors.add(port);
+ serverActors.add(part);
+ bindingTable.addEntry(serverRole, serverActors);
+ // the property playing the server role must also play the rtu role
+ port = ((org.eclipse.uml2.uml.Class) part.getType()).getOwnedPort("rtu", null);
+ if (port == null) {
+ if (((org.eclipse.uml2.uml.Class) part.getType()).getInheritedMember("rtu") != null &&
+ ((org.eclipse.uml2.uml.Class) part.getType()).getInheritedMember("rtu") instanceof org.eclipse.uml2.uml.Port) {
+ port = (org.eclipse.uml2.uml.Port) ((org.eclipse.uml2.uml.Class) part.getType()).getInheritedMember("rtu");
+ }
+ else {
+ System.out.println("Could not find a port rtu on part " + part.getName() + " : " + part.getType());
+ }
+ }
+ if (port != null) {
+ List<NamedElement> rtuActors = new ArrayList<NamedElement>();
+ rtuActors.add(port);
+ rtuActors.add(part);
+ bindingTable.addEntry(rtuRole, rtuActors);
+ }
+ }
+ }
+ }
+ }
+ List<NamedElement> connectorActors = new ArrayList<NamedElement>();
+ connectorActors.add(connector.getBase_Connector());
+ bindingTable.addEntry(connectorRole, connectorActors);
+ return bindingTable;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java
new file mode 100644
index 00000000000..b33d4053ed2
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java
@@ -0,0 +1,68 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.iconfigurators;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.qompass.designer.core.deployment.AllocUtils;
+import org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator;
+import org.eclipse.uml2.uml.InstanceSpecification;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Property;
+
+/**
+ * Configurator for the Eclipse animation server. This instance is systematically
+ * allocated to a node named "Eclipse" call event (for a state machine): it sets the
+ * portID attribute of the call event interceptor. The interceptor uses this
+ * attribute to initialize the portID attribute within the produced CallEvent
+ * data structure.
+ *
+ * @author ansgar
+ *
+ */
+public class AnimServiceConfigurator implements IInstanceConfigurator {
+
+ public final static String eclipseAnimService = "Eclipse"; //$NON-NLS-1$
+
+ /**
+ * Configure the instance of a CallEvent interceptor. The configuration parameter is the
+ * index of the port which gets intercepted. It is obtained via an enumeration
+ *
+ * @see org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator#configureInstance(org.eclipse.uml2.uml.InstanceSpecification, org.eclipse.uml2.uml.InstanceSpecification, org.eclipse.uml2.uml.Port)
+ *
+ * @param instance
+ * the instance that should be configured
+ * @param componentPart
+ * the part representing this instance
+ * @param context
+ * container context
+ */
+ @Override
+ public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstance)
+ {
+ EList<InstanceSpecification> nodes = AllocUtils.getAllNodesOrThreadsParent(parentInstance);
+ if (nodes.size() > 0) {
+ InstanceSpecification node = nodes.get(0);
+ // problem: instance specification is within intermediate model, thus incomplete.
+ // option: explicitly pre-create singletons (and allocate these?)
+ NamedElement animService = node.getNearestPackage().getMember(eclipseAnimService);
+ if (animService instanceof InstanceSpecification) {
+ AllocUtils.allocate(instance, (InstanceSpecification) animService);
+ return;
+ }
+ }
+ // throw new TransformationRTException(String.format("Cannot find node <%s> in platform definition", eclipseAnimService));
+ }
+
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java
new file mode 100644
index 00000000000..db9831cd43a
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.iconfigurators;
+
+import org.eclipse.papyrus.qompass.designer.core.deployment.DepPlanUtils;
+import org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator;
+import org.eclipse.uml2.uml.InstanceSpecification;
+import org.eclipse.uml2.uml.Property;
+
+/**
+ * Configurator of a call event (for a state machine): it sets the
+ * portID attribute of the call event interceptor. The interceptor uses this
+ * attribute to initialize the portID attribute within the produced CallEvent
+ * data structure.
+ *
+ * @author ansgar
+ *
+ */
+public class CallEventConfigurator implements IInstanceConfigurator {
+
+ public final static String portAttribute = "portID"; //$NON-NLS-1$
+
+ /**
+ * Configure the instance of a CallEvent interceptor. The configuration parameter is the
+ * index of the port which gets intercepted. It is obtained via an enumeration
+ *
+ * @see org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator#configureInstance(org.eclipse.uml2.uml.InstanceSpecification, org.eclipse.uml2.uml.InstanceSpecification, org.eclipse.uml2.uml.Port)
+ *
+ * @param instance
+ * the instance that should be configured
+ * @param componentPart
+ * the part representing this instance
+ * @param context
+ * container context
+ */
+ @Override
+ public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstance)
+ {
+ if (parentInstance != null) {
+ // make sure that there is an enum par port
+ // String literalName = "port_" + UMLTool.varName(context.port); //$NON-NLS-1$
+
+ // the associated enumeration is declared by the statemachine (which is included by the bootloader as well)
+
+ DepPlanUtils.configureProperty(instance, portAttribute, 0);
+ }
+ }
+
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIcallback.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIcallback.java
new file mode 100644
index 00000000000..74809d9cc9b
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIcallback.java
@@ -0,0 +1,162 @@
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import java.util.Iterator;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.ParameterDirectionKind;
+import org.eclipse.uml2.uml.Type;
+
+
+public class AMIcallback implements IMappingRule {
+
+ private static final String _REPLY = "_reply_"; //$NON-NLS-1$
+ private static final String _REQUEST = "_request_"; //$NON-NLS-1$
+ private static final String AMI_CB = "AMI_CB"; //$NON-NLS-1$
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getType();
+ if (!(type instanceof Interface)) {
+ return null;
+ }
+
+ Interface typingInterface = (Interface) type;
+ Class derivedType = MapUtil.getDerivedClass(p, AMI_CB);
+ Interface derivedRequestInterface = MapUtil.getDerivedInterface(p, _REQUEST);
+ Interface derivedReplyInterface = MapUtil.getDerivedInterface(p, _REPLY);
+ MapUtil.addUsage(derivedType, derivedRequestInterface); // caller can use (require) the request interface
+ MapUtil.addRealization(derivedType, derivedReplyInterface); // callers must implement (provide) the reply interface
+
+ if (!update) {
+ return derivedType;
+ }
+
+ // -----------------------------------------------
+ // calculate "request" interface (OUT parameter are removed)
+ // -----------------------------------------------
+ for (Operation operation : typingInterface.getOwnedOperations()) {
+ String name = operation.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedRequestInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedRequestInterface.createOwnedOperation(name, null, null);
+ }
+
+ // request operation contains only in and inout parameters
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ if ((parameter.getDirection() == ParameterDirectionKind.IN_LITERAL) ||
+ (parameter.getDirection() == ParameterDirectionKind.INOUT_LITERAL)) {
+
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedOperation.getOwnedParameter(paramName, paramType) == null) {
+ Parameter newParameter = derivedOperation.createOwnedParameter(parameter.getName(), parameter.getType());
+ newParameter.setDirection(parameter.getDirection());
+ newParameter.setLower(parameter.getLower());
+ newParameter.setUpper(parameter.getUpper());
+ }
+ }
+ }
+
+ // remove those parameters that exist in derived, but not original interface.
+ Iterator<Parameter> derivedParameters = derivedOperation.getOwnedParameters().iterator();
+ while (derivedParameters.hasNext()) {
+ Parameter parameter = derivedParameters.next();
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (operation.getOwnedParameter(paramName, paramType) == null) {
+ // not on in original interface, remove from derived as well
+ derivedParameters.remove();
+ }
+ }
+ }
+
+ // check whether operations in derived interface exist in original interface
+ // (remove, if not)
+ Iterator<Operation> derivedRequestOperations = derivedRequestInterface.getOwnedOperations().iterator();
+ while (derivedRequestOperations.hasNext()) {
+ Operation derivedOperation = derivedRequestOperations.next();
+ String name = derivedOperation.getName();
+ if (name == null) {
+ continue;
+ }
+ if (typingInterface.getOperation(name, null, null) == null) {
+ // not in typing interface, remove
+ derivedRequestOperations.remove();
+ }
+ }
+
+ // -----------------------------------------------
+ // calculate "reply" interface (with OUT and INOUT parameter transformed into in parameters)
+ // -----------------------------------------------
+ for (Operation operation : typingInterface.getOwnedOperations()) {
+ String name = operation.getName();
+
+ if (AMIpoll.hasOutParameters(operation)) {
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedReplyInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedReplyInterface.createOwnedOperation(name, null, null);
+ }
+
+ // each non-in parameter is in the poll operation.
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ if (parameter.getDirection() != ParameterDirectionKind.IN_LITERAL) { // OUT and INOUT
+
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedOperation.getOwnedParameter(paramName, paramType) == null) {
+ Parameter newParameter = derivedOperation.createOwnedParameter(parameter.getName(), parameter.getType());
+ newParameter.setDirection(ParameterDirectionKind.IN_LITERAL);
+ newParameter.setLower(parameter.getLower());
+ newParameter.setUpper(parameter.getUpper());
+ }
+ }
+ }
+
+ // remove those parameters that exist in derived, but not original interface.
+ Iterator<Parameter> derivedParameters = derivedOperation.getOwnedParameters().iterator();
+ while (derivedParameters.hasNext()) {
+ Parameter parameter = derivedParameters.next();
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (operation.getOwnedParameter(paramName, paramType) == null) {
+ // not on in original interface, remove from derived as well
+ derivedParameters.remove();
+ }
+ }
+ }
+ }
+
+ // check whether operations in derived interface exist in original interface
+ // (remove, if not)
+ Iterator<Operation> derivedReplyOperations = derivedReplyInterface.getOwnedOperations().iterator();
+ while (derivedRequestOperations.hasNext()) {
+ Operation derivedOperation = derivedReplyOperations.next();
+ String name = derivedOperation.getName();
+ if (name == null) {
+ continue;
+ }
+ if (typingInterface.getOperation(name, null, null) == null) {
+ // not in typing interface, remove
+ derivedReplyOperations.remove();
+ }
+ }
+
+ return derivedType;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ // TODO: insufficient condition
+ return (calcDerivedType(p, false) == null);
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIpoll.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIpoll.java
new file mode 100644
index 00000000000..220f2021465
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/AMIpoll.java
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import java.util.Iterator;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.ParameterDirectionKind;
+import org.eclipse.uml2.uml.Type;
+
+
+/**
+ * Implement a CORBA AMI style polling interface
+ * This is defined in the CORBA 3 standard in section 22.6.2
+ * A difference is that we do not return the poller object, but the client uses the original port.
+ * This has the consequence that it is not possible to make multiple asynchronous requests.
+ *
+ * A second difference is that we do not keep the normal methods in the same interface and prefix the
+ * new ones. (which would probably be a good idea).
+ *
+ */
+public class AMIpoll implements IMappingRule {
+
+ private static final String IAMI_POLL = "IAMIPoll_"; //$NON-NLS-1$
+ private static final String AMI_POLL = "AMIPoll_"; //$NON-NLS-1$
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getType();
+ if (!(type instanceof Interface)) {
+ return null;
+ }
+
+ Class derivedType = MapUtil.getDerivedClass(p, AMI_POLL);
+ Interface typingInterface = (Interface) type;
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, IAMI_POLL);
+ MapUtil.addUsage(derivedType, derivedInterface);
+
+ if (!update) {
+ return derivedType;
+ }
+
+ for (Operation operation : typingInterface.getOwnedOperations()) {
+ String name = operation.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedInterface.createOwnedOperation(name, null, null);
+ }
+
+ if (hasOutParameters(operation)) {
+ String pollName = name + "Poll"; //$NON-NLS-1$
+ Operation derivedPollOperation = derivedInterface.getOperation(pollName, null, null);
+ if (derivedPollOperation == null) {
+ derivedPollOperation = derivedInterface.createOwnedOperation(pollName, null, null);
+ }
+
+ // each non-in parameter is in the poll operation.
+ derivedPollOperation.createOwnedParameter("timeout", null); //$NON-NLS-1$
+
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ if (parameter.getDirection() != ParameterDirectionKind.IN_LITERAL) {
+
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedPollOperation.getOwnedParameter(paramName, paramType) == null) {
+ Parameter newParameter =
+ derivedPollOperation.createOwnedParameter(parameter.getName(), parameter.getType());
+ newParameter.setDirection(parameter.getDirection());
+ newParameter.setLower(parameter.getLower());
+ newParameter.setUpper(parameter.getUpper());
+ }
+ }
+ }
+ }
+ // each in and inout parameter is in the request operation.
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ if ((parameter.getDirection() == ParameterDirectionKind.IN_LITERAL) ||
+ (parameter.getDirection() == ParameterDirectionKind.INOUT_LITERAL)) {
+
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedOperation.getOwnedParameter(paramName, paramType) == null) {
+ Parameter newParameter =
+ derivedOperation.createOwnedParameter(parameter.getName(), parameter.getType());
+ newParameter.setDirection(parameter.getDirection());
+ newParameter.setLower(parameter.getLower());
+ newParameter.setUpper(parameter.getUpper());
+ }
+ }
+ }
+ // remove those parameters that exist in derived, but not original interface.
+ Iterator<Parameter> derivedParameters = derivedOperation.getOwnedParameters().iterator();
+ while (derivedParameters.hasNext()) {
+ Parameter parameter = derivedParameters.next();
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if ((!paramName.equals("timeout")) && //$NON-NLS-1$
+ (operation.getOwnedParameter(paramName, paramType) == null)) {
+ // not on in original interface, remove from derived as well
+ derivedParameters.remove();
+ }
+ }
+ }
+
+ // check whether operations in derived interface exist in original interface
+ // (remove, if not)
+ Iterator<Operation> derivedOperations = derivedInterface.getOwnedOperations().iterator();
+ while (derivedOperations.hasNext()) {
+ Operation derivedOperation = derivedOperations.next();
+ String name = derivedOperation.getName();
+ if (name == null) {
+ continue;
+ }
+ if (name.endsWith("Poll")) { //$NON-NLS-1$
+ // remove Poll postfix
+ name = name.substring(0, name.length() - 4);
+ }
+ if (typingInterface.getOperation(name, null, null) == null) {
+ // not in typing interface, remove
+ derivedOperations.remove();
+ }
+ }
+
+ return derivedType;
+ }
+
+ public static boolean hasOutParameters(Operation operation) {
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ if (parameter.getDirection() != ParameterDirectionKind.IN_LITERAL) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ // TODO: insufficient condition
+ return (calcDerivedType(p, false) == null);
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort.java
new file mode 100644
index 00000000000..3d08ffae8bf
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort.java
@@ -0,0 +1,132 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.papyrus.qompass.designer.core.OperationUtils;
+import org.eclipse.papyrus.qompass.designer.core.PortUtils;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Port;
+import org.eclipse.uml2.uml.Type;
+
+
+/**
+ * An extended Port in the sense of the DDS4CCM standard: a port typed with a component
+ * type. Since the component typing the port can have multiple provided and required
+ * ports, the ports are implicitly owned by the port. Conjugation on the level of an extended
+ * port level will conjugate all ports of the component typing the port.
+ *
+ * The derived interface that is provided will concatenate provided port names within the
+ * extended port with the port name and provided a "big" interface.
+ * The derived interface that is required is identical, except for a conjugation on the
+ * extended port level.
+ *
+ * Creates a fixed template binding that binds T (of the extended Port) to the used data type
+ *
+ * Here, the idea is that the port type is a classifier, e.g. the data type that is
+ * transported by a DDS port. The port kind is the extended port, e.g. DDSWrite.
+ *
+ * The derived property isExtended of FCM port-kind is true, if the class representing the port-kind owns at least one
+ * port
+ *
+ * TODO: This class has become obsolete now, since extended DDS ports are now supported via flattening
+ *
+ */
+@Deprecated
+public class ExtendedPort implements IMappingRule {
+
+ public static final String PROV_PREFIX = "P_"; //$NON-NLS-1$
+
+ public static final String REQ_PREFIX = "R_"; //$NON-NLS-1$
+
+ @Override
+ public boolean needsUpdate(org.eclipse.papyrus.FCM.Port p) {
+ return needsUpdate(p, false) ||
+ needsUpdate(p, true);
+ }
+
+ public boolean needsUpdate(org.eclipse.papyrus.FCM.Port p, boolean isRequired) {
+ return true;
+ }
+
+ @Override
+ public Type calcDerivedType(org.eclipse.papyrus.FCM.Port p, boolean update)
+ {
+ Type type = p.getType();
+ if (!(type instanceof Classifier)) {
+ return null;
+ }
+ Class extendedPort = p.getKind().getBase_Class();
+
+ String prefix = extendedPort.getName() + "_" + (p.getBase_Port().isConjugated() ? REQ_PREFIX : PROV_PREFIX); //$NON-NLS-1$
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, prefix, true);
+ if (!update) {
+ return derivedInterface;
+ }
+ if (derivedInterface == null) {
+ return null;
+ }
+ /*
+ * TemplateSignature signature = TemplateUtils.getSignature(type.getNearestPackage());
+ * if(signature != null) {
+ * Package model = Utils.getTop(derivedInterface);
+ * try {
+ * TemplateBinding binding =
+ * TemplateUtils.fixedBinding(model, extendedPort, (Classifier)type);
+ * Copy copy = new Copy(model, model, false);
+ * TemplateInstantiation ti = new TemplateInstantiation(copy, binding);
+ * // create a bound element of the extended port. Add bound class to derived interface class
+ * Class boundClass = ti.bindNamedElement(extendedPort);
+ * derivedInterface.getNearestPackage().getPackagedElements().add(boundClass);
+ * } catch (TransformationException e) {
+ * return null;
+ * }
+ * }
+ */
+ // obtain first template parameter = port type
+ // kind.getBase_Class().getNearestPackage().getTemplateParameter();
+
+ for (Port port : extendedPort.getOwnedPorts()) {
+ Interface derivedIntf = (p.getBase_Port().isConjugated()) ?
+ PortUtils.getRequired(port) :
+ PortUtils.getProvided(port);
+
+ if (derivedIntf != null) {
+ for (Operation op : derivedIntf.getAllOperations()) {
+ String name = port.getName() + "_" + op.getName(); //$NON-NLS-1$
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedInterface.createOwnedOperation(name, null, null);
+ OperationUtils.syncOperation(op, derivedOperation);
+ derivedOperation.setName(name);
+ }
+ else {
+ if (!OperationUtils.isSameOperation(derivedOperation, op, false)) {
+ OperationUtils.syncOperation(op, derivedOperation);
+ derivedOperation.setName(name);
+ }
+ }
+ }
+ }
+ }
+ return derivedInterface;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort2.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort2.java
new file mode 100644
index 00000000000..f12eadcdc4c
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ExtendedPort2.java
@@ -0,0 +1,138 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.papyrus.qompass.designer.core.PortUtils;
+import org.eclipse.papyrus.qompass.designer.core.transformations.PrefixConstants;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Port;
+import org.eclipse.uml2.uml.Type;
+
+
+/**
+ * An extended Port in the sense of the DDS4CCM standard: a port typed with a component
+ * type (the extended port, not the data type that is transported). Since the component typing
+ * the port can have multiple provided and required
+ * ports, the ports are implicitly owned by the port. Conjugation on the level of an extended
+ * port level will conjugate all ports of the component typing the port.
+ *
+ * The derived interface that is provided will allow a caller to access individual ports. It
+ * is therefore a reference to the interfaces get_<portName> operations provided by a
+ * component.
+ * The derived interface that is required is identical, except for a conjugation on the
+ * extended port level.
+ *
+ * What is the difference to ExtendedPort?
+ *
+ */
+public class ExtendedPort2 implements IMappingRule {
+
+ public static final String CONJ_PREFIX = "C2_"; //$NON-NLS-1$
+
+ public static final String NORM_PREFIX = "N2_"; //$NON-NLS-1$
+
+ @Override
+ public Type calcDerivedType(org.eclipse.papyrus.FCM.Port p, boolean update) {
+
+ Type type = p.getType();
+ if (!(type instanceof Class)) {
+ return null;
+ }
+
+ Class extendedPort = (Class) type;
+ boolean isConjugated = p.getBase_Port().isConjugated();
+ String prefix = isConjugated ? CONJ_PREFIX : NORM_PREFIX;
+ Class derivedClass = MapUtil.getDerivedClass(p, prefix, update);
+ Interface providedInterface = MapUtil.getDerivedInterface(p, prefix, update);
+ Interface requiredInterface = MapUtil.getDerivedInterface(p, prefix, update);
+ if (!update) {
+ return derivedClass;
+ }
+ if (derivedClass == null) {
+ return null;
+ }
+ for (Port port : extendedPort.getOwnedPorts()) {
+ // if the extended port is conjugated, each of the provided/required are (implicitly)
+ // conjugated [TODO: is PortUtils aware of it? - probably yes]
+ Interface reqIntf = PortUtils.getRequired(port);
+
+ if (reqIntf != null) {
+ String name = PrefixConstants.getP_Prefix + port.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = requiredInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = requiredInterface.createOwnedOperation(name, null, null);
+ }
+ }
+
+ Interface provIntf = PortUtils.getProvided(port);
+
+ if (provIntf != null) {
+ String name = PrefixConstants.getConnQ_Prefix + port.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = providedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = providedInterface.createOwnedOperation(name, null, null);
+ }
+ }
+ }
+ return derivedClass;
+ }
+
+ @Override
+ public boolean needsUpdate(org.eclipse.papyrus.FCM.Port p) {
+ return needsUpdate(p, false) ||
+ needsUpdate(p, true);
+ }
+
+ public boolean needsUpdate(org.eclipse.papyrus.FCM.Port p, boolean isConjugated) {
+ Type type = p.getBase_Port().getType();
+ if (!(type instanceof Class)) {
+ return false;
+ }
+
+ Class extendedPort = (Class) type;
+ String prefix = isConjugated ? CONJ_PREFIX : NORM_PREFIX;
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, prefix);
+
+ if (derivedInterface == null) {
+ return true;
+ }
+ for (Port port : extendedPort.getOwnedPorts()) {
+ // if the extended port is conjugated, each of the provided/required are (implicitly)
+ // conjugated [TODO: is PortUtils aware of it? - probably yes]
+ Interface provIntf = (isConjugated) ?
+ PortUtils.getRequired(port) :
+ PortUtils.getProvided(port);
+
+ if (provIntf != null) {
+ String name = PrefixConstants.getP_Prefix + port.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ProvideInterface.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ProvideInterface.java
new file mode 100644
index 00000000000..2432ddcdc42
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/ProvideInterface.java
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Type;
+
+public class ProvideInterface implements IMappingRule
+{
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getBase_Port().getType();
+ if (type instanceof Interface) {
+ return ((Interface) type);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ return false;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PullConsumer.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PullConsumer.java
new file mode 100644
index 00000000000..84c73d33c96
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PullConsumer.java
@@ -0,0 +1,162 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.papyrus.qompass.designer.core.Log;
+import org.eclipse.papyrus.qompass.designer.core.Utils;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.uml2.uml.Class;
+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.Operation;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.PrimitiveType;
+import org.eclipse.uml2.uml.Signal;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * Will generate a suitable callable interface pulling consumer. The port is typed with a primitive type
+ * or data type. The generated interface has a "<Type> pull as well as a "boolean hasData()" operation).
+ */
+public class PullConsumer implements IMappingRule {
+
+ public static String PULL_I_PREFIX = "PullConsumer_"; //$NON-NLS-1$
+
+ public static String PULL_C_PREFIX = "CPullConsumer_"; //$NON-NLS-1$
+
+ public static String PULL_OP_NAME = "pull"; //$NON-NLS-1$
+
+ public static String HASDATA_OP_NAME = "hasData"; //$NON-NLS-1$
+
+ public static String RET_PAR_NAME = "ret"; //$NON-NLS-1$
+
+ public static String BOOL_QNAME = "corba::Boolean"; //$NON-NLS-1$
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ Type type = p.getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PULL_I_PREFIX);
+ if (derivedInterface == null) {
+ return true;
+ }
+ Operation derivedOperation = derivedInterface.getOperation(PULL_OP_NAME, null, null);
+ if (derivedOperation == null) {
+ return true;
+ }
+ EList<Parameter> parameters = derivedOperation.getOwnedParameters();
+ if (parameters.size() != 1) {
+ return true;
+ } else {
+ Parameter parameter = parameters.get(0);
+ if (!parameter.getName().equals(RET_PAR_NAME)) {
+ return true;
+ }
+ if (parameter.getType() != type) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public static PullConsumer getInstance() {
+ if (instance == null) {
+ instance = new PullConsumer();
+ }
+ return instance;
+ }
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ org.eclipse.uml2.uml.Port umlPort = p.getBase_Port();
+ Element owner = umlPort.getOwner();
+ String ownerStr = ""; //$NON-NLS-1$
+ if (owner instanceof NamedElement) {
+ ownerStr = " of class " + ((NamedElement) owner).getQualifiedName(); //$NON-NLS-1$
+ }
+ Log.log(IStatus.INFO, Log.CALC_PORTKIND,
+ p.getKind().getBase_Class().getName() + " => GetRequired on " + umlPort.getName() + ownerStr);
+ Type type = p.getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Class derivedClass = MapUtil.getDerivedClass(p, PULL_C_PREFIX, update);
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PULL_I_PREFIX, update);
+ MapUtil.addUsage(derivedClass, derivedInterface);
+ if (!update) {
+ return derivedClass;
+ }
+ if (derivedInterface == null) {
+ return null;
+ }
+ // check whether operation already exists. Create, if not
+ Operation derivedOperationPull = derivedInterface.getOperation(PULL_OP_NAME, null, null);
+ if (derivedOperationPull == null) {
+ derivedOperationPull = derivedInterface.createOwnedOperation(PULL_OP_NAME, null, null, type);
+ }
+ EList<Parameter> parameters = derivedOperationPull.getOwnedParameters();
+ if (parameters.size() > 0) {
+ Parameter parameter = parameters.get(0);
+ if ((parameter.getName() == null) || (!parameter.getName().equals(RET_PAR_NAME))) {
+ parameter.setName(RET_PAR_NAME);
+ }
+ if (parameter.getType() != type) {
+ parameter.setType(type);
+ }
+ }
+ Package model = PackageUtil.getRootPackage(umlPort);
+ Element element = Utils.getQualifiedElement(model, BOOL_QNAME);
+ Type booleanType = null;
+ if (element instanceof Type) {
+ booleanType = (Type) element;
+ }
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperationHasData = derivedInterface.getOperation(HASDATA_OP_NAME, null, null);
+ if (derivedOperationHasData == null) {
+ derivedOperationHasData = derivedInterface.createOwnedOperation(HASDATA_OP_NAME, null, null, booleanType);
+ }
+
+ parameters = derivedOperationHasData.getOwnedParameters();
+ if (parameters.size() > 0) {
+ Parameter parameter = parameters.get(0);
+ if ((parameter.getName() == null) || (!parameter.getName().equals(RET_PAR_NAME))) {
+ parameter.setName(RET_PAR_NAME);
+ }
+ if ((booleanType != null) && (parameter.getType() != booleanType)) {
+ // added != null check
+ parameter.setType(booleanType);
+ }
+ }
+
+ return derivedClass;
+ } else {
+ return null;
+ }
+ }
+
+ protected static PullConsumer instance;
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushConsumer.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushConsumer.java
new file mode 100644
index 00000000000..f0375f8840e
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushConsumer.java
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.papyrus.qompass.designer.core.Log;
+import org.eclipse.uml2.uml.DataType;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.PrimitiveType;
+import org.eclipse.uml2.uml.Signal;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * Will generate a suitable called interface push consumer. The port is typed with a primitive type
+ * or data type. The generated interface has a "push (data <Type>)" operation ).
+ *
+ * The interface is identical to that of a PushProducer (and will be shared).
+ *
+ * @author ansgar
+ */
+public class PushConsumer implements IMappingRule {
+
+ public static String PUSH_OP_PREFIX = "push"; //$NON-NLS-1$
+
+ public static String PUSH_OP_PARNAME = "data"; //$NON-NLS-1$
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ Type type = p.getBase_Port().getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PushProducer.PUSH_I_PREFIX);
+ if (derivedInterface == null) {
+ return true;
+ }
+
+ Operation derivedOperation = derivedInterface.getOperation(PUSH_OP_PREFIX, null, null);
+ if (derivedOperation == null) {
+ return true;
+ }
+ EList<Parameter> parameters = derivedOperation.getOwnedParameters();
+ if (parameters.size() != 1) {
+ return true;
+ } else {
+ Parameter parameter = parameters.get(0);
+ if (!parameter.getName().equals(PUSH_OP_PARNAME)) {
+ return true;
+ }
+ if (parameter.getType() != type) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Log.log(IStatus.INFO, Log.CALC_PORTKIND,
+ p.getKind().getBase_Class().getName() + " => GetProvided on " + p.getBase_Port().getName());
+ Type type = p.getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PushProducer.PUSH_I_PREFIX, update);
+ if (!update) {
+ return derivedInterface;
+ }
+ if (derivedInterface == null) {
+ // may happen, if within template (do not want creation of derived interfaces in template)
+ return null;
+ }
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(PUSH_OP_PREFIX, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedInterface.createOwnedOperation(PUSH_OP_PREFIX, null, null);
+ }
+ EList<Parameter> parameters = derivedOperation.getOwnedParameters();
+ if (parameters.size() == 0) {
+ derivedOperation.createOwnedParameter(PUSH_OP_PARNAME, type);
+ } else {
+ parameters.get(0).setName(PUSH_OP_PARNAME);
+ parameters.get(0).setType(type);
+ }
+ return derivedInterface;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProdPullCons.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProdPullCons.java
new file mode 100644
index 00000000000..d719977a2db
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProdPullCons.java
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.DataType;
+import org.eclipse.uml2.uml.PrimitiveType;
+import org.eclipse.uml2.uml.Signal;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * Create a bidirectional port with a push producer and a pull consumer
+ * TODO: Objective is not clear
+ * Will generate a suitable callable interface pulling consumer. The port is typed with a primitive type
+ * or data type. The generated interface has a "<Type> pull as well as a "boolean hasData()" operation).
+ */
+public class PushProdPullCons implements IMappingRule {
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Class derivedClass = MapUtil.getDerivedClass(p, "PushProdPullcons", update);
+ if (!update) {
+ return derivedClass;
+ }
+
+ // obtain derived interface for other port kind (Caveat: some rules get the prefix from the
+ // name of the port kind attached to port "p" which would produce wrong results.
+ Type derivedInterfacePushProd = PushProducer.getInstance().calcDerivedType(p, update);
+ Type derivedInterfacePullCons = PullConsumer.getInstance().calcDerivedType(p, update);
+
+ /*
+ if (derivedInterface == null) {
+ return null;
+ }
+
+ if (!derivedInterface.getGenerals().contains(derivedInterfacePushProd)) {
+ derivedInterface.createGeneralization(derivedInterfacePushProd);
+ }
+ if (!derivedInterface.getGenerals().contains(derivedInterfacePullCons)) {
+ derivedInterface.createGeneralization(derivedInterfacePullCons);
+ }
+ return derivedInterface;
+ */
+ return null;
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ return PushProducer.getInstance().needsUpdate(p) ||
+ PullConsumer.getInstance().needsUpdate(p);
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProducer.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProducer.java
new file mode 100644
index 00000000000..e7933346b8f
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/PushProducer.java
@@ -0,0 +1,130 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.papyrus.qompass.designer.core.Log;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.DataType;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.PrimitiveType;
+import org.eclipse.uml2.uml.Signal;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * Will generate a suitable callable interface push provider. The port is typed with a primitive type
+ * or data type. The generated interface has a "push (data <Type>)" operation
+ *
+ * The interface is identical to that of a PushConsumer (and will be shared).
+ *
+ * @author ansgar
+ */
+public class PushProducer implements IMappingRule {
+
+ public static String PUSH_I_PREFIX = "Push_"; //$NON-NLS-1$
+
+ public static String PUSH_C_PREFIX = "CPush_"; //$NON-NLS-1$
+
+ public static String PUSH_OP_NAME = "push"; //$NON-NLS-1$
+
+ public static String PUSH_OP_PARNAME = "data"; //$NON-NLS-1$
+
+ public static PushProducer getInstance() {
+ if (instance == null) {
+ instance = new PushProducer();
+ }
+ return instance;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ Type type = p.getBase_Port().getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PUSH_I_PREFIX);
+ if (derivedInterface == null) {
+ return true;
+ }
+
+ Operation derivedOperation = derivedInterface.getOperation(PUSH_OP_NAME, null, null);
+ if (derivedOperation == null) {
+ return true;
+ }
+ EList<Parameter> parameters = derivedOperation.getOwnedParameters();
+ if (parameters.size() != 1) {
+ return true;
+ } else {
+ Parameter parameter = parameters.get(0);
+ if (!parameter.getName().equals(PUSH_OP_PARNAME)) {
+ return true;
+ }
+ if (parameter.getType() != type) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Log.log(IStatus.INFO, Log.CALC_PORTKIND, p.getKind().getBase_Class().getName() + " => GetRequired on " + p.getBase_Port().getName());
+ Type type = p.getType();
+
+ if ((type instanceof PrimitiveType) || (type instanceof DataType) || (type instanceof Signal)) {
+
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, PUSH_I_PREFIX, update);
+ Class derivedType = MapUtil.getDerivedClass(p, PUSH_C_PREFIX, update);
+ MapUtil.addUsage(derivedType, derivedInterface);
+ if (!update) {
+ return derivedType;
+ }
+ if (derivedInterface == null) {
+ // may happen, if within template (do not want creation of derived interfaces in template)
+ return null;
+ }
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(PUSH_OP_NAME, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedInterface.createOwnedOperation(PUSH_OP_NAME, null, null);
+ }
+ EList<Parameter> parameters = derivedOperation.getOwnedParameters();
+ if (parameters.size() == 0) {
+ derivedOperation.createOwnedParameter(PUSH_OP_PARNAME, type);
+ } else {
+ Parameter parameter = parameters.get(0);
+ if (!parameter.getName().equals(PUSH_OP_PARNAME)) {
+ parameter.setName(PUSH_OP_PARNAME);
+ }
+ if (parameter.getType() != type) {
+ parameter.setType(type);
+ }
+ }
+ return derivedType;
+ } else {
+ return null;
+ }
+ }
+
+ protected static PushProducer instance;
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/TemplatePort.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/TemplatePort.java
new file mode 100644
index 00000000000..62dce7e7709
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/TemplatePort.java
@@ -0,0 +1,183 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.FCM.PortKind;
+import org.eclipse.papyrus.FCM.util.ITemplateMappingRule;
+import org.eclipse.papyrus.qompass.designer.core.Utils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateInstantiation;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils;
+import org.eclipse.papyrus.qompass.designer.core.transformations.LazyCopier;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException;
+import org.eclipse.papyrus.qompass.designer.core.transformations.filters.FixTemplateSync;
+import org.eclipse.papyrus.qompass.modellibs.core.Activator;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Classifier;
+import org.eclipse.uml2.uml.Namespace;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageableElement;
+import org.eclipse.uml2.uml.Port;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.TemplateSignature;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+
+/**
+ * An extended Port in the sense of the DDS4CCM standard: a port typed with a component
+ * type. Since the component typing the port can have multiple provided and required
+ * ports, the ports are implicitly owned by the port. Conjugation on the level of an extended
+ * port level will conjugate all ports of the component typing the port.
+ *
+ * The derived interface that is provided will concatenate provided port names within the
+ * extended port with the port name and provided a "big" interface.
+ * The derived interface that is required is identical, except for a conjugation on the
+ * extended port level.
+ *
+ * Creates a fixed template binding that binds T (of the extended Port) to the used data type
+ *
+ * Here, the idea is that the port type is a classifier, e.g. the data type that is
+ * transported by a DDS port. The port kind is the extended port, e.g. DDSWrite.
+ *
+ * The derived property isExtended of FCM port-kind is true, if the class representing the port-kind owns at least one
+ * port
+ *
+ * @author ansgar
+ *
+ */
+public class TemplatePort implements ITemplateMappingRule {
+
+ @Override
+ public Type calcDerivedType(org.eclipse.papyrus.FCM.Port p, boolean update) {
+ // TODO: unify template mapping rule and normal one.
+ return null;
+ }
+
+ @Override
+ public PortKind getBoundType(org.eclipse.papyrus.FCM.Port p)
+ {
+ Port port = p.getBase_Port();
+ Type type = port.getType();
+ if (!(type instanceof Classifier)) {
+ return null;
+ }
+ if (p.getKind() == null) {
+ return null;
+ }
+ Class extendedPort = p.getKind().getBase_Class();
+ TemplateSignature signature = TemplateUtils.getSignature(extendedPort.getNearestPackage());
+ Package pkgTemplate = signature.getNearestPackage();
+ if (pkgTemplate != null) {
+ EList<Namespace> path = TemplateUtils.relativePathWithMerge(extendedPort, pkgTemplate);
+
+ String name = pkgTemplate.getName() + "_" + type.getName(); //$NON-NLS-1$
+ Package model = PackageUtil.getRootPackage(port);
+ Package pkg = model.getNestedPackage(name);
+ if (pkg == null) {
+ model = Utils.getFirstLevel(port); // try whether package template exists here
+ // required for target model with additional "root" folder
+ pkg = model.getNestedPackage(name);
+ }
+ if (pkg != null) {
+ for (Namespace pathElem : path) {
+ pkg = pkg.getNestedPackage(pathElem.getName());
+ if (pkg == null) {
+ return null;
+ }
+ }
+ PackageableElement boundClass = pkg.getPackagedElement(extendedPort.getName());
+ if (boundClass != null) {
+ return UMLUtil.getStereotypeApplication(boundClass, PortKind.class);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void updateBinding(org.eclipse.papyrus.FCM.Port p) {
+ Port port = p.getBase_Port();
+ Type type = port.getType();
+ if (!(type instanceof Classifier)) {
+ return;
+ }
+ Class extendedPort = p.getKind().getBase_Class();
+
+ TemplateSignature signature = TemplateUtils.getSignature(extendedPort.getNearestPackage());
+ if (signature != null) {
+ Package model = PackageUtil.getRootPackage(port);
+ try {
+ TemplateBinding binding =
+ TemplateUtils.fixedBinding(model, extendedPort, (Classifier) type);
+ LazyCopier copy = new LazyCopier(model, model, false, true);
+ TemplateInstantiation ti = new TemplateInstantiation(copy, binding);
+ // remove listener synchronizing implementation, since it would add derived
+ // elements for the extended port itself (e.g. provided operations)
+ if (copy.postCopyListeners.contains(FixTemplateSync.getInstance())) {
+ copy.postCopyListeners.remove(FixTemplateSync.getInstance());
+ }
+
+ // create a bound element of the extended port. Add bound class to derived interface class
+ ti.bindElement(extendedPort);
+ } catch (TransformationException e) {
+ Activator.log.error("Could not create template binding", e);
+ }
+ }
+ }
+
+ @Override
+ public boolean needsUpdate(org.eclipse.papyrus.FCM.Port p) {
+ Port port = p.getBase_Port();
+ Type type = port.getType();
+ if (!(type instanceof Classifier)) {
+ return false;
+ }
+ if (p.getKind() == null) {
+ return false;
+ }
+ Class extendedPort = p.getKind().getBase_Class();
+ TemplateSignature signature = TemplateUtils.getSignature(extendedPort.getNearestPackage());
+ Package pkgTemplate = signature.getNearestPackage();
+ if (pkgTemplate != null) {
+ EList<Namespace> path = TemplateUtils.relativePathWithMerge(extendedPort, pkgTemplate);
+
+ String name = pkgTemplate.getName() + "_" + type.getName(); //$NON-NLS-1$
+ Package model = PackageUtil.getRootPackage(port);
+ Package pkg = model.getNestedPackage(name);
+ if (pkg == null) {
+ model = Utils.getFirstLevel(port); // try whether package template exists here
+ // required for target model with additional "root" folder
+ pkg = model.getNestedPackage(name);
+ }
+ if (pkg != null) {
+ for (Namespace pathElem : path) {
+ pkg = pkg.getNestedPackage(pathElem.getName());
+ if (pkg == null) {
+ return true;
+ }
+ }
+ PackageableElement boundClass = pkg.getPackagedElement(extendedPort.getName());
+ if (boundClass != null) {
+ if (UMLUtil.getStereotypeApplication(boundClass, PortKind.class) != null) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseConjIntf.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseConjIntf.java
new file mode 100644
index 00000000000..cee9f055d01
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseConjIntf.java
@@ -0,0 +1,187 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import java.util.Iterator;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.ParameterDirectionKind;
+import org.eclipse.uml2.uml.Type;
+
+/**
+ * Use a conjugated interface (!= conjugated port), i.e. an interface in which the roles "in" and "out"
+ * of each parameter of an operation are inversed. This transformation is useful in the context of transforming
+ * a "push" interface into a "pull" interface, i.e. instead of calling and providing values values to the
+ * called component via "in", the called components queries us and obtains these values as out parameters.
+ * TODO: This rules is currently not used, since data flow operation are currently either based on a datatype
+ * or a MARTE FlowPort
+ *
+ * @author ansgar
+ *
+ */
+public class UseConjIntf implements IMappingRule {
+
+ private static final String CONJ_INTF_TYPE = "ConjIntfType_"; //$NON-NLS-1$
+ private static final String CONJ_INTF = "ConjIntf_"; //$NON-NLS-1$
+
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getBase_Port().getType();
+ if (!(type instanceof Interface)) {
+ return null;
+ }
+
+ Interface typingInterface = (Interface) type;
+ Interface derivedInterface = MapUtil.getDerivedInterface(p, CONJ_INTF, update);
+ Class derivedType = MapUtil.getDerivedClass(p, CONJ_INTF_TYPE, update);
+ if (!update) {
+ return derivedType;
+ }
+ if (derivedInterface == null) {
+ return null;
+ }
+ MapUtil.addUsage(derivedType, derivedInterface);
+ for (Operation operation : typingInterface.getOwnedOperations()) {
+ String name = operation.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ derivedOperation = derivedInterface.createOwnedOperation(name, null, null);
+ }
+
+ // TODO: move to Copy (factor code, ensure that these values are handled in case of model copies ...)
+ derivedOperation.setIsAbstract(operation.isAbstract());
+ derivedOperation.setIsStatic(operation.isStatic()); // (does not make sense for an interface, if true)
+ derivedOperation.setIsUnique(operation.isUnique());
+ derivedOperation.setIsQuery(operation.isQuery());
+
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedOperation.getOwnedParameter(paramName, paramType) == null) {
+ Parameter newParameter =
+ derivedOperation.createOwnedParameter(parameter.getName(), parameter.getType());
+ ParameterDirectionKind direction = parameter.getDirection();
+ if (direction == ParameterDirectionKind.IN_LITERAL) {
+ newParameter.setDirection(ParameterDirectionKind.OUT_LITERAL);
+ }
+ else if (direction == ParameterDirectionKind.OUT_LITERAL) {
+ newParameter.setDirection(ParameterDirectionKind.IN_LITERAL);
+ }
+ else {
+ newParameter.setDirection(direction);
+ }
+ newParameter.setLower(parameter.getLower());
+ newParameter.setUpper(parameter.getUpper());
+ }
+ }
+ // remove those parameters that exist in derived, but not original interface.
+ Iterator<Parameter> derivedParameters = derivedOperation.getOwnedParameters().iterator();
+ while (derivedParameters.hasNext()) {
+ Parameter parameter = derivedParameters.next();
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (operation.getOwnedParameter(paramName, paramType) == null) {
+ // not on in original interface, remove from derived as well
+ derivedParameters.remove();
+ }
+ }
+ }
+
+ // check whether operations in derived interface exist in original interface
+ // (remove, if not)
+ Iterator<Operation> derivedOperations = derivedInterface.getOwnedOperations().iterator();
+ while (derivedOperations.hasNext()) {
+ Operation derivedOperation = derivedOperations.next();
+ String name = derivedOperation.getName();
+ if (typingInterface.getOperation(name, null, null) == null) {
+ // not in typing interface, remove
+ if (derivedInterface.getOperations().remove(derivedOperation)) {
+ derivedOperations = derivedInterface.getOwnedOperations().iterator();
+ }
+ }
+ }
+ return derivedType;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ Type type = p.getType();
+ if (!(type instanceof Interface)) {
+ return false;
+ }
+
+ Interface typingInterface = (Interface) type;
+ Interface derivedInterface = MapUtil.getOrCreateDerivedInterface(p, CONJ_INTF);
+ Class derivedType = MapUtil.getOrCreateDerivedClass(p, CONJ_INTF_TYPE);
+ if ((derivedInterface == null) || (derivedType == null)) {
+ return true;
+ }
+ for (Operation operation : typingInterface.getOwnedOperations()) {
+ String name = operation.getName();
+
+ // check whether operation already exists. Create, if not
+ Operation derivedOperation = derivedInterface.getOperation(name, null, null);
+ if (derivedOperation == null) {
+ return true;
+ }
+
+ // TODO: move to Copy (factor code, ensure that these values are handled in case of model copies ...)
+ derivedOperation.setIsAbstract(operation.isAbstract());
+ derivedOperation.setIsStatic(operation.isStatic()); // (does not make sense for an interface, if true)
+ derivedOperation.setIsUnique(operation.isUnique());
+ derivedOperation.setIsQuery(operation.isQuery());
+
+ for (Parameter parameter : operation.getOwnedParameters()) {
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (derivedOperation.getOwnedParameter(paramName, paramType) == null) {
+ return true;
+ }
+ }
+ // remove those parameters that exist in derived, but not original interface.
+ Iterator<Parameter> derivedParameters = derivedOperation.getOwnedParameters().iterator();
+ while (derivedParameters.hasNext()) {
+ Parameter parameter = derivedParameters.next();
+ String paramName = parameter.getName();
+ Type paramType = parameter.getType();
+ if (operation.getOwnedParameter(paramName, paramType) == null) {
+ // not on in original operation
+ return true;
+ }
+ }
+ }
+
+ // check whether operations in derived interface exist in original interface
+ // (remove, if not)
+ Iterator<Operation> derivedOperations = derivedInterface.getOwnedOperations().iterator();
+ while (derivedOperations.hasNext()) {
+ Operation derivedOperation = derivedOperations.next();
+ String name = derivedOperation.getName();
+ if (typingInterface.getOperation(name, null, null) == null) {
+ // not in typing interface
+ return true;
+ }
+ }
+ return false;
+ }
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseInterface.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseInterface.java
new file mode 100644
index 00000000000..26af9111517
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/mappingrules/UseInterface.java
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * Copyright (c) 2013 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:
+ * Ansgar Radermacher ansgar.radermacher@cea.fr
+ *
+ *****************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.mappingrules;
+
+import org.eclipse.papyrus.FCM.Port;
+import org.eclipse.papyrus.FCM.util.IMappingRule;
+import org.eclipse.papyrus.FCM.util.MapUtil;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Interface;
+import org.eclipse.uml2.uml.Type;
+
+
+public class UseInterface implements IMappingRule
+{
+ @Override
+ public Type calcDerivedType(Port p, boolean update) {
+ Type type = p.getType();
+ if (type instanceof Interface) {
+ Class useType = MapUtil.getDerivedClass(p, "Use_", update); //$NON-NLS-1$
+ MapUtil.addUsage(useType, (Interface) type);
+ return useType;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean needsUpdate(Port p) {
+ return false;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AMIPull.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AMIPull.xtend
new file mode 100644
index 00000000000..d1e1fb28303
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AMIPull.xtend
@@ -0,0 +1,34 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.Marshalling.*
+
+class AMIPull {
+ def operation_(Operation operation) '''
+ «IF operation.name.endsWith("Poll")»
+ // comment polling function
+ if (!resultArrived) {
+ // wait for result, condition will be fired upon arrival
+ TimeVal timeVal = TimeVal::current () + timeout;
+ m_cond.waitUpto (timeout);
+ }
+ «operation.unmarshall»
+ }
+ «IF operation.type != null»return retValue;«ENDIF»
+ «ELSE»
+ // TODO: need suitable constant dimensioning
+ pBuffer = &buffer[500]; // grows backwards
+ int operationID = ID_[operation.name/];
+
+ // now marshall in and inout parameters via ASN.1
+ «operation.marshall»
+ BEncAsnContent (&amp;pBuffer, &amp;operationID);
+
+ pthread_t pt;
+ pthread_create (&amp;pt, NULL, staticDispatch, (void *) this);
+ // TODO: add semaphore which assures that subsequent calls to [operation.name/] are not executed before dispatch
+ // has removed the parameters from the pBuffer stack (pBuffer can be corrupted).
+ // even worse: buffer will be deallocated even without a 2nd call!
+ «ENDIF»
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AsyncCalls.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AsyncCalls.xtend
new file mode 100644
index 00000000000..fa7cb846212
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/AsyncCalls.xtend
@@ -0,0 +1,57 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.Class
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.Marshalling.*
+
+class AsyncCalls {
+ def asyncCall(Operation operation) '''
+ // TODO: need suitable constant dimensioning
+ pBuffer = &buffer[500]; // grows backwards
+ «operation.marshall»
+ int operationID = ID_[operation.name/];
+ BEncAsnContent (&amp;pBuffer, &amp;operationID);
+
+ pthread_t pt;
+ pthread_create (&amp;pt, NULL, staticDispatch, (void *) this);
+ // TODO: add semaphore which assures that subsequent calls to «operation.name» are not executed before dispatch
+ // has removed the parameters from the pBuffer stack (pBuffer can be corrupted).
+ '''
+
+ def dispatch_(Class clazz) '''
+ int operationID;
+ BDecAsnContent (&pBuffer, operationID);
+ switch (operationID) {
+ «FOR operation : clazz.ownedOperations»
+ case ID_«operation.name»
+ {
+
+ // delegate call to executor
+ rconn->«operation.cppCall»;
+ break;
+ }
+ «ENDFOR»
+ }
+ '''
+
+ def dispatchWithThreadPool(Class clazz) '''
+ int operationID;
+ BDecAsnContent (&pBuffer, operationID);
+ switch (operationID) {
+ «FOR operation : clazz.ownedOperations»
+ case ID_«operation.name»
+ {
+ «operation.unmarshall»
+ // delegate call to executor
+ rconn->«operation.cppCall»;
+ «IF operation.type != null»«operation.type.cppType» ret = «ENDIF»rconn->«operation.cppCall»;
+ «operation.marshallOutInout»
+ resultsReady = 1;
+ break;
+ }
+ «ENDFOR»
+ }
+ }
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/BehaviorUtil.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/BehaviorUtil.java
new file mode 100644
index 00000000000..e815c2c332b
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/BehaviorUtil.java
@@ -0,0 +1,111 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend;
+
+import org.eclipse.uml2.uml.Behavior;
+import org.eclipse.uml2.uml.BehavioredClassifier;
+import org.eclipse.uml2.uml.Class;
+import org.eclipse.uml2.uml.Constraint;
+import org.eclipse.uml2.uml.OpaqueBehavior;
+import org.eclipse.uml2.uml.OpaqueExpression;
+import org.eclipse.uml2.uml.Operation;
+import org.eclipse.uml2.uml.Parameter;
+import org.eclipse.uml2.uml.ParameterDirectionKind;
+import org.eclipse.uml2.uml.Transition;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLPackage;
+
+public class BehaviorUtil {
+ private static final String DEFAULT_LANGUAGE = "C++"; //$NON-NLS-1$
+
+ public static void set(Behavior behavior, String selectLanguage, String textblock) {
+ if (behavior instanceof OpaqueBehavior) {
+ OpaqueBehavior ob = (OpaqueBehavior) behavior;
+ if (ob.getLanguages().size() == 0) {
+ ob.getLanguages().add(DEFAULT_LANGUAGE);
+ ob.getBodies().add(textblock);
+ }
+ else {
+ int i = 0;
+ for (String language : ob.getLanguages()) {
+ if (selectLanguage.equals(language)) {
+ if (i < ob.getBodies().size()) {
+ ob.getBodies().set(i, textblock);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public static void set(Behavior behavior, String textblock) {
+ set(behavior, DEFAULT_LANGUAGE, textblock);
+ }
+
+ public static OpaqueBehavior createOpaqueBehavior(BehavioredClassifier clazz, Operation operation) {
+ OpaqueBehavior ob = (OpaqueBehavior)
+ clazz.createOwnedBehavior(operation.getName(), UMLPackage.eINSTANCE.getOpaqueBehavior());
+ ob.setSpecification(operation);
+ return ob;
+ }
+
+ public static OpaqueBehavior createOpaqueEffect(Transition transition) {
+ OpaqueBehavior ob = (OpaqueBehavior)
+ transition.createEffect("", UMLPackage.eINSTANCE.getOpaqueBehavior()); //$NON-NLS-1$
+ return ob;
+ }
+
+ public static OpaqueExpression createOpaqueExpression(Constraint constraint, String guardCode) {
+ OpaqueExpression oe = (OpaqueExpression)
+ constraint.createSpecification("", null, UMLPackage.eINSTANCE.getOpaqueExpression()); //$NON-NLS-1$
+ oe.getLanguages().add(DEFAULT_LANGUAGE);
+ oe.getBodies().add(guardCode);
+ return oe;
+ }
+
+ public static String body(Constraint constraint) {
+ if (constraint.getSpecification() instanceof OpaqueExpression) {
+ OpaqueExpression oe = (OpaqueExpression) constraint.getSpecification();
+ if (oe.getBodies().size() > 0) {
+ return oe.getBodies().get(0);
+ }
+ }
+ return constraint.getSpecification().stringValue();
+ }
+
+ /**
+ * Create an operation with an operation return type
+ *
+ * @param clazz
+ * @param name
+ * @param retType
+ * @return
+ */
+ public static Operation createOperation(Class clazz, String name, Type retType) {
+ Operation operation = clazz.createOwnedOperation(name, null, null);
+ if (retType != null) {
+ Parameter parameter = operation.createOwnedParameter("ret", retType); //$NON-NLS-1$
+ parameter.setDirection(ParameterDirectionKind.RETURN_LITERAL);
+ }
+ return operation;
+ }
+
+ public static String body(Behavior behavior) {
+ return body(behavior, DEFAULT_LANGUAGE);
+ }
+
+ public static String body(Behavior behavior, String selectLanguage) {
+ if (behavior instanceof OpaqueBehavior) {
+ OpaqueBehavior ob = (OpaqueBehavior) behavior;
+ int i = 0;
+ for (String language : ob.getLanguages()) {
+ if (selectLanguage.equals(language)) {
+ if (i < ob.getBodies().size()) {
+ return ob.getBodies().get(i);
+ }
+ break;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/CppUtils.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/CppUtils.xtend
new file mode 100644
index 00000000000..fb028cc5f16
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/CppUtils.xtend
@@ -0,0 +1,81 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.papyrus.qompass.designer.core.UMLTool
+import org.eclipse.uml2.uml.NamedElement
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.Parameter
+import org.eclipse.uml2.uml.ParameterDirectionKind
+import org.eclipse.uml2.uml.Type
+
+class CppUtils {
+
+ /**
+ * create the C++ signature for an operation (including parenthesis)
+ */
+ public static def cppSignature(Operation operation) '''
+ «operation.name»(«FOR parameter : operation.ownedParameters SEPARATOR(', ')»
+ «parameter.cppParameter»
+ «ENDFOR»
+ '''
+
+
+ /**
+ * make a C++ call, pass all parameters except the return parameter
+ */
+ public static def cppCall(Operation operation) '''
+ «operation.name»(«FOR parameter : UMLTool.parametersNonRet(operation) SEPARATOR(', ')»
+ «parameter.name»
+ «ENDFOR»)
+ '''
+
+ /**
+ * make a C++ call, pass all parameters except the return parameter, prefix with "return",
+ * if there is a return type in the operations declaration
+ */
+ public static def returnCppCall(Operation operation) '''
+ «IF (operation.type != null)»return «ENDIF»«operation.cppCall»
+ '''
+
+ public static def cppParameter(Parameter parameter) '''
+ «parameter.type»«IF (parameter.direction == ParameterDirectionKind.OUT)»_out«ENDIF» «parameter.name»
+ '''
+
+ public static def cppType(Type type) '''
+ «IF (type.qualifiedName == 'UMLPrimitiveTypes::Boolean')»
+ bool
+ «ELSEIF (type.qualifiedName == 'UMLPrimitiveTypes::Integer')»
+ int
+ «ELSE»
+ «UMLTool.dereferenceTypedef(type)»
+ «ENDIF»
+ '''
+
+
+ public static def cppRetType(Operation operation) '''
+ «IF (operation.type == null)»
+ void
+ «ELSE»
+ «operation.type.cppType»
+ «ENDIF»
+ '''
+
+ /**
+ * Open a set of C++ namespaces associated with the packages of of the passed named element
+ * TODO: use indentTab? => requires making this script recursive
+ * Need to include referenced types (assuming a naming convention?
+ */
+ public static def openNamespace(NamedElement namedElement) '''
+ «FOR ns : UMLTool.usedNamespaces(namedElement).reverse»
+ namespace «ns.name»
+ «ENDFOR»
+ '''
+
+ /**
+ * Close a set of C++ namespaces associated with the packages of of the passed named element
+ */
+ public static def closeNamespace(NamedElement namedElement) '''
+ «FOR ns : UMLTool.usedNamespaces(namedElement)»
+ }; // of namespace [ns.name/]
+ «ENDFOR»
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/FIFO.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/FIFO.xtend
new file mode 100644
index 00000000000..59440deec7b
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/FIFO.xtend
@@ -0,0 +1,13 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.DataType
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext
+
+class FIFO {
+ def activate(DataType datatype) '''
+ if (m_size == 0) {
+ cerr << "Warning: size of FIFO is not properly configured (size = 0)" << endl;
+ }
+ m_fifo = new «TransformationContext.pkgTemplateParameter("T")»[m_size];
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/GlobalConstants.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/GlobalConstants.xtend
new file mode 100644
index 00000000000..b2a19cce408
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/GlobalConstants.xtend
@@ -0,0 +1,56 @@
+/*******************************************************************************
+* Copyright (c) 2014 Zeligsoft (2009) Limited and others.
+* 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
+*******************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+class GlobalConstants {
+ public static val QUAL_NAME_SEP = "."
+ public static val FUNC_NAME_QUAL_NAME_SEP = "__"
+ public static val FUNC_NAME_PART_SEP = "____"
+ public static val INJECT_FUNC_NAME = "inject"
+ public static val INITIALIZE_FUNC_NAME = "initialize"
+ public static val STATE_FUNC_PREFIX = "state_"
+ public static val JUNCTION_FUNC_PREFIX = "junction_"
+ public static val CHOICE_FUNC_PREFIX = "choice_"
+ public static val ACTION_CHAIN_FUNC_PREFIX = "actionchain_"
+ public static val ACTION_FUNC_PREFIX = "action_"
+ public static val GUARD_FUNC_PREFIX = "guard_"
+ public static val USER_ACTION_FUNC_PREFIX = "useraction_"
+ public static val USER_GUARD_FUNC_PREFIX = "userguard_"
+ public static val EXIT_ACTION_FUNC_PREFIX = "exitaction_"
+ public static val ENTRY_ACTION_FUNC_PREFIX = "entryaction_"
+ public static val TRANS_ACTION_FUNC_PREFIX = "transitionaction_"
+ public static val SAVE_HISTORY_FUNC_NAME = "save_history"
+ public static val CHECK_HISTORY_FUNC_NAME = "check_history"
+ public static val CHECK_HISTORY_FUNC_PREFIX = "checkhistory_"
+ public static val CURRENT_STATE_FIELD_NAME = "currentState"
+ public static val HISTORY_TABLE_NAME = "history"
+ public static val UNDEFINED = "SPECIAL_INTERNAL_STATE_UNDEFINED"
+ public static val UNVISITED = "SPECIAL_INTERNAL_STATE_UNVISITED"
+ public static val STATE_TYPE_NAME = "State"
+ public static val PORT_TYPE_NAME = "Port"
+ public static val SIGNAL_TYPE_NAME = "Signal"
+ public static val INJECT_FUNC_PARAM = "msg"
+ public static val INITIALIZE_FUNC_PARAM = "msg"
+ public static val STATE_FUNC_PARAM = "msg"
+ public static val JUNC_FUNC_PARAM = "msg"
+ public static val CHOICE_FUNC_PARAM = "msg"
+ public static val CHAIN_FUNC_PARAM = "msg"
+ public static val ACTION_FUNC_PARAM = "msg"
+ public static val ACTION_DATA_VARIABLE = "rtdata"
+ public static val EMPTY_ACTION_COMMENT = "// (Automatically generated stub for an empty action)"
+ public static val MISSING_CODE_COMMENT = "// (No C++ code found for this action)"
+ public static val MISSING_CONSTRAINT_BODY = "false"
+ public static val FRESH_NAME_PREFIX = "new_"
+ public static val FRESH_ENTRYPOINT_NAME_PREFIX = "new_entrypoint_"
+ public static val FRESH_EXITPOINT_NAME_PREFIX = "new_exitpoint_"
+ public static val FRESH_CHOICEPOINT_NAME_PREFIX = "new_choice_"
+ public static val FRESH_JUNCTIONPOINT_NAME_PREFIX = "new_junction_"
+ public static var FRESH_TRANSITION_NAME_PREFIX = "new_transition_"
+
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/Marshalling.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/Marshalling.xtend
new file mode 100644
index 00000000000..02d93031b6a
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/Marshalling.xtend
@@ -0,0 +1,51 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import static extension org.eclipse.papyrus.qompass.designer.core.UMLTool.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.cppType
+import org.eclipse.uml2.uml.Parameter
+
+class Marshalling {
+ def static marshall(Operation operation) '''
+ // now marshall in and inout parameters via ASN.1
+ «FOR parameter : operation.parametersInInout»
+ «parameter.marshall»
+ «ENDFOR»
+ '''
+
+ def static marshallOutInout(Operation operation) '''
+ // now marshall out and inout parameters via ASN.1
+ «FOR parameter : operation.parametersOutInout»
+ «parameter.marshall»
+ «ENDFOR»
+ '''
+
+ def static marshall(Parameter parameter) '''
+ {
+ «parameter.type.cppType» varName_ASN = «parameter.name»;
+ BEncAsnContent (&pBuffer, &varName_ASN);
+ }
+ '''
+
+ def static unmarshall(Operation operation) '''
+ «FOR parameter : operation.parametersInInout.reverse»
+ «parameter.unmarshall»
+ «ENDFOR»
+ '''
+
+ def static unmarshallOutInout(Operation operation) '''
+ «FOR parameter : operation.parametersOutInout.reverse»
+ «parameter.unmarshall»
+ «ENDFOR»
+ '''
+
+ def static unmarshall(Parameter parameter) '''
+ «parameter.type.cppType» «parameter.name»
+ {
+ «parameter.type.cppType» varName_ASN;
+ BDecAsnContent (&pBuffer, &varName_ASN);
+ «parameter.name» = varName_ASN;
+ }
+ '''
+
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/MultipleReceptacle.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/MultipleReceptacle.xtend
new file mode 100644
index 00000000000..0f73ff273e2
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/MultipleReceptacle.xtend
@@ -0,0 +1,14 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.cppCall
+
+class MultipleReceptacle {
+ def operation_(Operation operation) '''
+ for (int i=0; i&lt;9; i++) {
+ if (rconn[i] != 0) {
+ rconn[i]->«operation.cppCall»;
+ }
+ }
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineGen.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineGen.xtend
new file mode 100644
index 00000000000..310526b1998
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineGen.xtend
@@ -0,0 +1,412 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.emf.common.util.BasicEList
+import org.eclipse.emf.common.util.EList
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.papyrus.C_Cpp.Ptr
+import org.eclipse.papyrus.FCM.DerivedElement
+import org.eclipse.papyrus.qompass.designer.core.StUtils
+import org.eclipse.papyrus.qompass.designer.core.Utils
+import org.eclipse.papyrus.qompass.designer.core.UMLTool
+import org.eclipse.papyrus.qompass.designer.core.extensions.IXtend
+import org.eclipse.papyrus.qompass.designer.core.sync.InterfaceSync
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException
+import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil
+import org.eclipse.uml2.uml.Behavior
+import org.eclipse.uml2.uml.BehavioredClassifier
+import org.eclipse.uml2.uml.CallEvent
+import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.OpaqueExpression
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.Pseudostate
+import org.eclipse.uml2.uml.PseudostateKind
+import org.eclipse.uml2.uml.Reception
+import org.eclipse.uml2.uml.Signal
+import org.eclipse.uml2.uml.SignalEvent
+import org.eclipse.uml2.uml.State
+import org.eclipse.uml2.uml.StateMachine
+import org.eclipse.uml2.uml.TimeEvent
+import org.eclipse.uml2.uml.Transition
+import org.eclipse.uml2.uml.Trigger
+import org.eclipse.uml2.uml.Type
+import org.eclipse.uml2.uml.ValueSpecification
+import org.eclipse.uml2.uml.Vertex
+import org.eclipse.uml2.uml.util.UMLUtil
+
+import static org.eclipse.papyrus.qompass.designer.core.EnumService.*
+import static org.eclipse.papyrus.qompass.designer.vsl.ParseVSL.*
+
+import static extension org.eclipse.papyrus.qompass.designer.core.UMLTool.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.BehaviorUtil.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.cppCall
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.StateMachineUtil.*
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil
+import org.eclipse.uml2.uml.UMLPackage
+import org.eclipse.uml2.uml.Enumeration
+
+class StateMachineGen implements IXtend {
+
+ Class clazz
+
+ boolean ooPattern = true;
+
+ def getStateMachine(Class clazz) {
+ // organized in a loop. But effectively supports single state machine
+ for (smBehavior : (clazz as BehavioredClassifier).ownedBehaviors.filter[it instanceof StateMachine]) {
+ return smBehavior as StateMachine
+ }
+ return null
+ }
+
+ def activate(Class clazz) {
+ val sm = clazz.stateMachine
+ val flattener = new UMLFlattener
+ flattener.transform(sm)
+ activate(clazz, sm)
+ }
+
+ def activate(Class clazz, StateMachine sm) '''
+ m_currentState = STATE_«sm.region.initialState.name»;
+#ifdef SM_VERBOSE
+ cout << "SM «clazz.name»: in state «sm.region.initialState.name»" << endl;
+#endif
+ for (;;) {
+ processEvents();
+ }
+ '''
+
+ def processEvents(Class clazz) {
+ val sm = clazz.stateMachine
+ // - Option to put processElements into original class (but, would need to copy dependencies & attributes)
+ // create new operation in class owning the state machine.
+ // val operation = clazz.createOperation("processEvents", null)
+ // val ob = clazz.createOpaqueBehavior(operation)
+ // ob.set(clazz.processEventsSM(sm).toString)
+ // return "executor->processEvents();"
+ this.clazz = clazz
+ return clazz.processEventsSM(sm)
+ }
+
+ def eventInterceptor(Operation operation) '''
+ «/*TODO: need better way to detect signal*/»
+ «operation.eventInterceptorCommon»
+ event.portID = portID;
+ out->writeEvent(event);
+
+ «IF (operation.type != null)»return «ENDIF»rconn->«operation.cppCall»;
+ '''
+
+ /**
+ * OO variant of event interceptor. Adds call event to pool and
+ * then calls the original method (handled by LW container)
+ */
+ def eventInterceptorOO(Operation operation) '''
+ «operation.eventInterceptorCommon»
+ '''
+
+ def eventInterceptorCommon(Operation operation) '''
+ «val derivedElement = UMLUtil.getStereotypeApplication(operation, DerivedElement)»
+ «IF (derivedElement != null) && (derivedElement.source instanceof Reception)»
+ «val signal = (derivedElement.source as Reception).signal»
+ // create event with global signal ID
+ core::ContainerServices::CallEvent_ event;
+ event.operationID = «literal(SIGNAL_ENUM, operation.name)»;
+ // map signal into value-buffer and copy attributes
+ ::«signal.qualifiedName» * signal = (::«signal.qualifiedName» *) &event.params;
+ «FOR attribute : signal.ownedAttributes»
+ signal->«attribute.name» = «attribute.name»;
+ «ENDFOR»
+ «PackageUtil.getRootPackage(operation).declareDependencyToSignalIDs»
+ «UMLTool.declareDependency(TransformationContext.classifier, signal)»
+ «ELSE»
+ // create event with operationID/portID and pass call
+ core::ContainerServices::CallEvent_ event;
+ «IF ooPattern»
+ event.operationID = OP_ID_«operation.name»;
+ «ELSE»
+ event.operationID = ID_«operation.name»;
+ «ENDIF»
+ «ENDIF»
+ '''
+
+ def processEventsSM(BehavioredClassifier clazz, StateMachine sm) '''
+ // processEvents body - generated by Qompass
+ //
+ // supports ports «FOR port : (clazz as Class).ownedPorts» «literal('PortEnum_'+clazz.name, 'port_'+clazz.name+'_'+port.name)»«ENDFOR»
+
+ core::ContainerServices::CallEvent_ event;
+ int timeout;
+ int newState;
+ bool needsTrigger;
+
+ switch(m_currentState) {
+ «FOR state : sm.region.subvertices»
+ case «literal('LStateIDs_'+clazz.name, 'STATE_'+state.name)»:
+ // -------- treatment of accepted events
+ «state.acceptableEvents»
+ break;
+ «ENDFOR»
+ default:
+ OSAL_ERROR ("Inconsistent state");
+ break;
+ }
+ if (animOut != 0) {
+ animOut->enterState(newState, «clazz.fragment»);
+ }
+ '''
+
+ /*
+ * Pass the actual to which the port is bound. In case of a CallEvent, pass the implemented interface
+ * (Not the class to which the state machine is bound). This is useful in the context of components
+ * whose ports implement an interface
+ */
+ def cetrigger(Operation operation) {
+ val intf = operation.implementsInterface
+ if (intf != null) {
+ val packageRef = intf.boundPackageRef
+ // declare dependency to OperationIDs enumeration
+ packageRef.declareDependencyToOperationIDs
+ '''«packageRef.qualifiedName»::ID_«operation.name»'''
+ }
+ else {
+ // create operationIDs literal
+ literal("LOperationIDs", '''OP_ID_«operation.name»''')
+ }
+ }
+
+ // Use service for global enumerations
+ def setrigger(Trigger trigger) {
+ val se = trigger.event as SignalEvent
+ literal(SIGNAL_ENUM, InterfaceSync.SIG_PREFIX + se.signal.name)
+ }
+
+ /**
+ * create code for acceptable events
+ *
+ * big restriction: will only analyse first of possibly multiple triggers
+ */
+ def acceptableEvents(Vertex state) '''
+ // loop on state
+ // execute action ...
+ timeout = -1; // no timeout by default
+ «FOR transition : state.outgoings»
+ «IF transition.triggers.size > 0»
+ «val trigger = transition.triggers.get(0)»
+ «IF (trigger.event instanceof TimeEvent)»
+ «val timeEvent = trigger.event as TimeEvent»
+ // transition «transition.name» - trigger: TimeEvent, expression «(timeEvent.when.expr as OpaqueExpression).bodies.get(0)».
+ timeout = «getDurationFromVSL((timeEvent.when.expr as OpaqueExpression).bodies.get(0))»/1000;
+ «ENDIF»
+ «ENDIF»
+ «ENDFOR»
+
+ «IF ((state instanceof State) && (state as State).entry != null)»
+ // execute entry action
+ executor->«(state as State).entry.name»();
+ «ENDIF»
+
+ needsTrigger = true;
+
+ «IF hasTransitionWithoutTrigger(state)»
+ «FOR transition : state.outgoings»
+ «IF transition.triggers.size == 0»
+ «IF transition.guard != null»
+ «transition.guard.specification.createGuardFct(null)»
+ if (executor->«transition.guard.specification.name»()) {
+ «ENDIF»
+ newState = STATE_«transition.target.name»;
+#ifdef SM_VERBOSE
+ cout << "SM «clazz.name»: transition to state «transition.target.name»" << endl;
+#endif
+ «IF (transition.effect != null)»
+ executor->«effectName(transition)»();
+ «ENDIF»
+ needsTrigger = false;
+ «IF transition.guard != null»
+ }
+ «ENDIF»
+ «ENDIF»
+ «ENDFOR»
+ «ENDIF»
+
+ if (needsTrigger) {
+ // get an event from the pool.
+ «IF ooPattern»
+ event = eventPool.readEvent(timeout);
+ «ELSE»
+ event = ep->readEvent(timeout);
+ «ENDIF»
+ }
+ else {
+ event.operationID = -1;
+ }
+
+ «val allOutgoings = state.outgoings»
+ «FOR transition : allOutgoings»
+ «IF transition.triggers.size > 0»
+ // has «transition.triggers.size» outgoing transitions
+ «val trigger = transition.triggers.get(0)»
+ «IF (trigger.event instanceof TimeEvent)»
+ // transition «transition.name» - trigger: TimeEvent (there should be at most one outgoing timed transition per state).
+ if (event.operationID == core::ContainerServices::EventPool::ID_TIMEOUT) {
+ «IF transition.guard != null»
+ «transition.guard.specification.createGuardFct(null)»
+ if (executor->«transition.guard.specification.name»()) {
+ «ENDIF»
+ newState = STATE_«transition.target.name»;
+#ifdef SM_VERBOSE
+ cout << "SM «clazz.name»: transition to state «transition.target.name»" << endl;
+#endif
+ «IF (transition.effect != null)»
+ executor->«effectName(transition)»();
+ «ENDIF»
+ «IF transition.guard != null»
+ }
+ «ENDIF»
+ }
+ «ENDIF»
+ «IF (trigger.event instanceof CallEvent)»
+ // transition «trigger.name» - trigger: CallEvent («trigger.event.name»), operation «(trigger.event as CallEvent).operation.name»
+ if (event.operationID == «cetrigger((trigger.event as CallEvent).operation)») {
+ newState = STATE_«transition.target.name»;
+#ifdef SM_VERBOSE
+ cout << "SM «clazz.name»: transition to state «transition.target.name»" << endl;
+#endif
+ «IF (transition.effect != null)»
+ executor->«effectName(transition)»();
+ «ENDIF»
+ }
+ «ENDIF»
+ «IF (trigger.event instanceof SignalEvent)»
+ «val signalEvent = trigger.event as SignalEvent»
+ // transition «trigger.name» - trigger: SignalEvent («signalEvent.name»), signal «signalEvent.signal.name»
+ if (event.operationID == «setrigger(trigger)») {
+ «IF (transition.effect != null) || (transition.guard != null)»
+ // map signal to parameter section
+ ::«signalEvent.signal.qualifiedName» * signal = (::«signalEvent.signal.qualifiedName» *) &event.params;
+ «ENDIF»
+ «IF transition.guard != null»
+ «transition.guard.specification.createGuardFct(signalEvent)»
+ if (executor->«transition.guard.specification.name»(signal)) {
+ «ENDIF»
+ newState = STATE_«transition.target.name»;
+#ifdef SM_VERBOSE
+ cout << "SM «clazz.name»: transition to state «transition.target.name» (due to signal «signalEvent.signal.name»)" << endl;
+#endif
+ «IF (transition.effect != null)»
+ «transition.effect.addSignalParameter(signalEvent.signal)»
+ executor->«effectName(transition)»(«IF signalEvent.signal.attributes.size > 0»signal«ENDIF»);
+ «ENDIF»
+ // ok = EvQUEUE ;
+ «IF transition.guard != null»
+ }
+ «ENDIF»
+ }
+ «ENDIF»
+ «ENDIF»
+ «ENDFOR»
+
+ if (newState != m_currentState) {
+ m_currentState = newState;
+ «IF ((state instanceof State) && (state as State).exit != null)»
+ // execute exit action
+ executor->«(state as State).exit.name»();
+ «ENDIF»
+
+
+ }
+ '''
+
+ def boolean hasTransitionWithoutTrigger(Vertex state) {
+ for (transition : state.outgoings) {
+ if (transition.triggers.size == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ def EList<Transition> calculateTransitions(Vertex state) {
+ val allOutgoings = new BasicEList<Transition>
+ allOutgoings.addAll(state.outgoings)
+ for (transition : state.outgoings) {
+ if (transition.target instanceof Pseudostate) {
+ val ps = transition.target as Pseudostate
+ if (ps.kind == PseudostateKind.JUNCTION_LITERAL) {
+ allOutgoings.addAll(ps.outgoings.clone)
+ }
+ }
+ }
+ return allOutgoings
+ }
+
+ /**
+ * Effects are moved from behaviors embedded into transitions towards behaviors of the class. Calculate the name of these
+ * effects. The class FilterStateMachines moves the effects (TODO: single name calculation)
+ */
+ def effectName(Transition transition) {
+ // transition.containingStateMachine.name + "_" + transition.effect.name
+ if (transition.effect.name == null) {
+ throw new TransformationException(
+ String.format("effect of transition has no name (in SM %s)", transition.containingStateMachine.name))
+ }
+ transition.effect.name
+ }
+
+ def void addSignalParameter(Behavior behavior, Signal signal) {
+ if (behavior.ownedParameters.size == 0) {
+ val parameter = behavior.createOwnedParameter("signal", signal)
+ StereotypeUtil.apply(parameter, Ptr)
+ }
+ }
+
+ def void moveBehavior(String newName, Class tmClass, Behavior effect) {
+ val copiedEffect = EcoreUtil.copy(effect)
+ if (tmClass.getOwnedOperation(newName, null, null) != null) {
+ // has already been added
+ return;
+ }
+ val operation = tmClass.createOwnedOperation(newName, null, null);
+ for (parameter : effect.getOwnedParameters()) {
+ val newParameter = EcoreUtil.copy(parameter);
+ operation.getOwnedParameters().add(newParameter);
+ StUtils.copyStereotypes(parameter, newParameter);
+ }
+ copiedEffect.setSpecification(operation);
+ copiedEffect.setName(newName);
+ tmClass.getOwnedBehaviors().add(copiedEffect);
+ }
+
+ static final String CLIB_BOOL = "AnsiCLibrary::bool"
+
+ def void createGuardFct(ValueSpecification specification, SignalEvent event) {
+ val name = specification.getName()
+
+ if (clazz.getOwnedBehavior(name) != null) {
+ return
+ }
+ var booleanNamedElement = Utils.getQualifiedElement(TransformationContext.sourceRoot, CLIB_BOOL);
+
+ if (booleanNamedElement instanceof Type) {
+ val booleanType = TransformationContext.copier.getCopy(booleanNamedElement) as Type
+ val operation = clazz.createOperation(name, booleanType as Type)
+ if (event != null) {
+ val sigParam = operation.createOwnedParameter("signal", event.signal)
+ StereotypeUtil.apply(sigParam, Ptr)
+ }
+ val ob = clazz.createOpaqueBehavior(operation)
+ if (specification instanceof OpaqueExpression) {
+ ob.getLanguages().addAll(specification.getLanguages());
+ for (String body : specification.getBodies()) {
+ ob.getBodies().add("return " + body + ";");
+ }
+ }
+ }
+ else {
+ System.out.println("was");
+ }
+ // if (tmClass.getOwnedOperation(newName, null, null) != null) {
+ // copiedEffect.setSpecification(operation);
+ }
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineUtil.java b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineUtil.java
new file mode 100644
index 00000000000..d33d2a0c9fb
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StateMachineUtil.java
@@ -0,0 +1,260 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend;
+
+import java.util.Collection;
+
+import org.eclipse.emf.common.util.BasicEList;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.papyrus.qompass.designer.core.UMLTool;
+import org.eclipse.papyrus.qompass.designer.core.Utils;
+import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils;
+import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext;
+import org.eclipse.papyrus.uml.tools.utils.PackageUtil;
+import org.eclipse.uml2.uml.NamedElement;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.PackageableElement;
+import org.eclipse.uml2.uml.Pseudostate;
+import org.eclipse.uml2.uml.PseudostateKind;
+import org.eclipse.uml2.uml.Region;
+import org.eclipse.uml2.uml.State;
+import org.eclipse.uml2.uml.StateMachine;
+import org.eclipse.uml2.uml.TemplateBinding;
+import org.eclipse.uml2.uml.Transition;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLPackage;
+import org.eclipse.uml2.uml.Vertex;
+
+
+public class StateMachineUtil {
+ public static Region region(State state) {
+ EList<Region> regions = state.getRegions();
+ if (regions.size() > 0) {
+ return regions.get(0);
+ }
+ return null;
+ }
+
+ public static Region region(StateMachine stateMachine) {
+ EList<Region> regions = stateMachine.getRegions();
+ if (regions.size() > 0) {
+ return regions.get(0);
+ }
+ return null;
+ }
+
+ public static EList<State> subStates(State state) {
+ Region region = region(state);
+ return (region != null) ? states(region) : new BasicEList<State>();
+ }
+
+ public static EList<State> states(StateMachine stateMachine) {
+ Region region = region(stateMachine);
+ return (region != null) ? states(region) : new BasicEList<State>();
+ }
+
+ public static EList<State> states(Region region) {
+ EList<State> states = new BasicEList<State>();
+ for (org.eclipse.uml2.uml.Vertex vertex : region.getSubvertices()) {
+ if (vertex instanceof State) {
+ states.add((State) vertex);
+ }
+ }
+ return states;
+ }
+
+ public static EList<Pseudostate> entryPoints(State state) {
+ EList<Pseudostate> pseudoStates = new BasicEList<Pseudostate>();
+ for (Pseudostate pseudoState : state.getConnectionPoints()) {
+ if (pseudoState.getKind() == PseudostateKind.ENTRY_POINT_LITERAL) {
+ pseudoStates.add(pseudoState);
+ }
+ }
+ return pseudoStates;
+ }
+
+ public static EList<Pseudostate> exitPoints(State state) {
+ EList<Pseudostate> pseudoStates = new BasicEList<Pseudostate>();
+ for (Pseudostate pseudoState : state.getConnectionPoints()) {
+ if (pseudoState.getKind() == PseudostateKind.EXIT_POINT_LITERAL) {
+ pseudoStates.add(pseudoState);
+ }
+ }
+ return pseudoStates;
+ }
+
+ public static EList<Pseudostate> junctionPoints(Region region) {
+ return filteredPseudoStates(region, PseudostateKind.JUNCTION_LITERAL);
+ }
+
+ public static EList<Pseudostate> choicePoints(Region region) {
+ return filteredPseudoStates(region, PseudostateKind.CHOICE_LITERAL);
+ }
+
+ public static EList<Pseudostate> filteredPseudoStates(Region region, PseudostateKind kind) {
+ EList<Pseudostate> pseudoStates = new BasicEList<Pseudostate>();
+ for (Vertex vertex : region.getSubvertices()) {
+ if (vertex instanceof Pseudostate) {
+ Pseudostate pseudoState = (Pseudostate) vertex;
+ if (pseudoState.getKind() == kind) {
+ pseudoStates.add(pseudoState);
+ }
+ }
+ }
+ return pseudoStates;
+ }
+
+ public static Pseudostate firstPseudoState(Region region, PseudostateKind kind) {
+ for (Vertex vertex : region.getSubvertices()) {
+ if (vertex instanceof Pseudostate) {
+ Pseudostate pseudoState = (Pseudostate) vertex;
+ if (pseudoState.getKind() == kind) {
+ return pseudoState;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @return The set of all transitions ending indirectly on the state.
+ * This is, those which end on one of the state's entry points.
+ */
+ public static Collection<Transition> indirectIncomings(State state) {
+ EList<Transition> indirectIncoming = new BasicEList<Transition>();
+ for (Pseudostate p : entryPoints(state)) {
+ for (Transition t : p.getIncomings()) {
+ indirectIncoming.add(t);
+ }
+ }
+ return indirectIncoming;
+ }
+
+ /**
+ * @return The set of all transitions ending indirectly on the state.
+ * This is, those which end on one of the state's entry points.
+ */
+ public static Collection<Transition> indirectOutgoings(State state) {
+ EList<Transition> indirectIncoming = new BasicEList<Transition>();
+ for (Pseudostate p : entryPoints(state)) {
+ for (Transition t : p.getIncomings()) {
+ indirectIncoming.add(t);
+ }
+ }
+ return indirectIncoming;
+ }
+
+
+ /**
+ * @return The set of all direct and indirect incoming transitions to the state.
+ */
+ public static Collection<Transition> allIncomings(State state) {
+ EList<Transition> allIncoming = new BasicEList<Transition>();
+ for (Transition t : state.getIncomings()) {
+ allIncoming.add(t);
+ }
+ allIncoming.addAll(indirectIncomings(state));
+ return allIncoming;
+ }
+
+ /**
+ * @return The set of all direct and indirect incoming transitions to the state.
+ */
+ public static Collection<Transition> allOutgoings(State state) {
+ EList<Transition> allIncoming = new BasicEList<Transition>();
+ for (Transition t : state.getIncomings()) {
+ allIncoming.add(t);
+ }
+ allIncoming.addAll(indirectOutgoings(state));
+ return allIncoming;
+ }
+
+ /**
+ * Adds all the inner elements of a composite state to self, except for the
+ * initial, entry, exit and history pseudo-states.
+ *
+ * This operation moves those elements, as it removes them from their
+ * original container and sets their owner to the recipient.
+ */
+ public static void moveContents(Region targetRegion, State source) {
+ Region sourceRegion = region(source);
+ EList<Vertex> vertices = new BasicEList<Vertex>(sourceRegion.getSubvertices());
+ for (Vertex v : vertices) {
+ // move states and pseudostates
+ targetRegion.getSubvertices().add(v);
+ }
+ EList<Transition> transitions = new BasicEList<Transition>(sourceRegion.getTransitions());
+ for (Transition t : transitions) {
+ targetRegion.getTransitions().add(t);
+ }
+ }
+
+ public static Pseudostate initialState(Region region) {
+ return firstPseudoState(region, PseudostateKind.INITIAL_LITERAL);
+ }
+
+ public static Pseudostate deepHistory(Region region) {
+ return firstPseudoState(region, PseudostateKind.DEEP_HISTORY_LITERAL);
+ }
+
+ public static State createState(Region region, String name) {
+ return (State) region.createSubvertex(name, UMLPackage.eINSTANCE.getState());
+ }
+
+ public static Pseudostate createPseudostate(Region region, String name) {
+ return (Pseudostate) region.createSubvertex(name, UMLPackage.eINSTANCE.getPseudostate());
+ }
+
+ /**
+ * Return the bound package in the context of template instantiation for a given actual.
+ *
+ * This is required by the state machine template which needs to access operation IDs
+ * provided by the call interceptor.
+ *
+ * @param actual
+ * The actual for template binding
+ * @return
+ */
+ public static Package boundPackageRef(Type actual) {
+ for (Package nestedPkg : PackageUtil.getRootPackage(actual).getNestedPackages()) {
+ // search for bound package templates who are bound to the same actual
+ // TODO: search is ambiguous, if same actual is used more than once
+ if (nestedPkg.getTemplateBindings().size() > 0) {
+ TemplateBinding binding = nestedPkg.getTemplateBindings().get(0);
+ if (actual == TemplateUtils.getFirstActualFromBinding(binding)) {
+ return nestedPkg;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Declares a dependency from the current classifier which is produced by template instantiation
+ * to the element (enum) "OperationIDs", if found within the passed package.
+ *
+ * @param pkg
+ * @return
+ */
+ public static void declareDependencyToOperationIDs(Package pkg) {
+ PackageableElement type = pkg.getPackagedElement("OperationIDs"); //$NON-NLS-1$
+ if (type instanceof Type) {
+ UMLTool.declareDependency(TransformationContext.classifier, (Type) type);
+ }
+ }
+
+ /**
+ * Declares a dependency from the current classifier which is produced by template instantiation
+ * to the element (enum) "SignalIDs", if found within the passed package.
+ *
+ * @param pkg
+ * the package in which an enumeration is looked up
+ * @return
+ */
+ public static void declareDependencyToSignalIDs(Package pkg) {
+ NamedElement type = Utils.getQualifiedElement(pkg, "globalenums::" + SIGNAL_ENUM); //$NON-NLS-1$
+ if (type instanceof Type) {
+ UMLTool.declareDependency(TransformationContext.classifier, (Type) type);
+ }
+ }
+
+ static final String SIGNAL_ENUM = "SignalIDs";
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StructBasedMarshalling.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StructBasedMarshalling.xtend
new file mode 100644
index 00000000000..89d085b3937
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/StructBasedMarshalling.xtend
@@ -0,0 +1,25 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import static extension org.eclipse.papyrus.qompass.designer.core.UMLTool.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.cppType
+
+// TODO: original model code does effectively do more than marshalling
+class StructBasedMarshalling {
+ def static marshall(Operation operation) '''
+ struct ParamData {
+ «FOR parameter : operation.parametersInInout»
+ «parameter.type.cppType» «parameter.name»;
+ «ENDFOR»
+ };
+ Event event;
+ event.ID = [operation.name/];
+ event.kind = CallEvent;
+ ParamData * data = &event.params;
+ «FOR parameter : operation.parametersInInout»
+ data->[parameter.name/] = [parameter.name/];
+ «ENDFOR»
+ out->dispatch(event);
+ '''
+
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/SyncCalls.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/SyncCalls.xtend
new file mode 100644
index 00000000000..96952f2f8d1
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/SyncCalls.xtend
@@ -0,0 +1,13 @@
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Operation
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.CppUtils.*
+
+class SyncCalls {
+ def syncCall(Operation operation) '''
+ // put pre-interceptors here
+ [comment type is a derived property containing the operations return type/]
+ «IF operation.type != null»return «ENDIF»rconn->«operation.cppCall»;
+ // put post-interceptors here
+ '''
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLAction.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLAction.xtend
new file mode 100644
index 00000000000..3cbc6f2da3a
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLAction.xtend
@@ -0,0 +1,58 @@
+/*******************************************************************************
+* Copyright (c) 2014 Zeligsoft, CEA and others.
+* 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
+*******************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.uml2.uml.Behavior
+import java.util.List
+import java.util.ArrayList
+
+/**
+ * An action in the sense of the invocation of a behavior.
+ * This means that the actual behavior is not described here. The action
+ * is referencing the behavior and providing information how to invoke the
+ * behavior.
+ * The action has no prefix: the name of the referenced behavior needs to be prefixed, if necessary
+ *
+ * @author Ansgar (based on code from eposse)
+ *
+ */
+class UMLAction {
+
+ /** Source UMLRT model element. */
+ @Accessors Behavior origin
+
+ // list of parameters for a call, simply a list of strings. if null => no parameters
+ public List<String> callParams;
+
+ new(Behavior origin) {
+ this.origin = origin
+ }
+
+ /**
+ * Add a parameter
+ */
+ def addParam(String parameter) {
+ if (callParams == null) {
+ callParams = new ArrayList<String>()
+ }
+ callParams.add = parameter
+ }
+
+ def getSpecification() {
+ origin.specification
+ }
+
+ def getFuncName() {
+ origin.name
+ }
+
+ override toString() '''Action(«origin.name»)'''
+
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLChain.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLChain.xtend
new file mode 100644
index 00000000000..05bf596b9a6
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLChain.xtend
@@ -0,0 +1,91 @@
+/*******************************************************************************
+* Copyright (c) 2014 Zeligsoft (2009) Limited and others.
+* 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
+*******************************************************************************/
+
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import java.util.HashMap
+import java.util.List
+import java.util.Map
+import org.eclipse.uml2.uml.Behavior
+import org.eclipse.uml2.uml.Transition
+import org.eclipse.xtend.lib.annotations.Accessors
+
+/**
+ * A chain of state entry, exit and transition actions for a "flat"
+ * {@link Transition}.
+ *
+ * @author eposse
+ *
+ */
+class UMLChain {
+
+ @Accessors List<UMLAction> actions
+ @Accessors Transition owner
+
+ static Map<Transition, UMLChain> chains;
+
+ new () {
+ actions = newArrayList
+ }
+
+ new (List<UMLAction> actions) {
+ this.actions = newArrayList(actions) // We need this to be mutable.
+ }
+
+ def static void initChains() {
+ chains = new HashMap<Transition, UMLChain>();
+ }
+
+ /**
+ * Return the chain of behaviors associated with a transition
+ * IF the chain does not exist yet, it will be created (and stored in a hash map)
+ * @param t
+ * @return
+ */
+ def static UMLChain chain(Transition t) {
+ var UMLChain chain = chains.get(t)
+ if (chain == null) {
+ chain = new UMLChain()
+ chain.setOwner(t)
+ chains.put(t, chain)
+ }
+ return chain
+ }
+
+ def append(UMLAction action) {
+ actions.add(action)
+ return this
+ }
+
+ def append(Behavior behavior) {
+ if (behavior != null) {
+ append(new UMLAction(behavior))
+ }
+ return this
+ }
+
+ def prepend(UMLAction action) {
+ actions.add(0, action)
+ return this
+ }
+
+ def prepend(Behavior behavior) {
+ prepend(new UMLAction(behavior))
+ return this
+ }
+
+ def getOwner() {
+ owner
+ }
+
+ def setOwner(Transition t) {
+ owner = t
+ // add transition effect to action list
+ append(t.effect)
+ }
+} \ No newline at end of file
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlatModel2Cpp.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlatModel2Cpp.xtend
new file mode 100644
index 00000000000..fe1b522e4bf
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlatModel2Cpp.xtend
@@ -0,0 +1,667 @@
+/*******************************************************************************
+* Copyright (c) 2014 Zeligsoft, CEA and others.
+* 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
+*******************************************************************************/
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Port
+import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.Property
+import org.eclipse.uml2.uml.State
+import org.eclipse.uml2.uml.StateMachine
+import org.eclipse.uml2.uml.Transition
+import java.util.Map
+import org.eclipse.uml2.uml.NamedElement
+import java.util.Collection
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.StateMachineUtil.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.BehaviorUtil.*
+import org.eclipse.uml2.uml.UMLPackage
+import org.eclipse.uml2.uml.Enumeration
+import org.eclipse.uml2.uml.EnumerationLiteral
+import org.eclipse.uml2.uml.Pseudostate
+import org.eclipse.uml2.uml.PseudostateKind
+import org.eclipse.uml2.uml.Operation
+import org.eclipse.uml2.uml.OpaqueBehavior
+import org.eclipse.uml2.uml.Parameter
+import org.eclipse.uml2.uml.CallEvent
+import org.eclipse.uml2.uml.Stereotype
+import org.eclipse.uml2.uml.Type
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.UMLChain.chain
+import java.util.List
+import org.eclipse.papyrus.qompass.designer.core.EnumService
+
+/**
+ * This class contains the transformation from flat UML-RT state machines to the
+ * C/C++ language model.
+ *
+ * It implements the algorithms described in the technical report
+ *
+ * E. Posse. "Transforming flat UML-RT State Machines to a C/C++ language model".
+ * Technical Report ZTR-2014-EP-002, Version 2, Zeligsoft, Sep 2014.
+ *
+ * Ansgar Radermacher (CEA): translation to UML transformation
+ * @author eposse
+ */
+class UMLFlatModel2Cpp {
+
+ /**
+ * The CppCodePattern that is being used for this transformation operation.
+ */
+
+ /** The source state machine to transform */
+ StateMachine machine
+ Class clazz
+
+ /** Elements that go into the generated model. */
+ Enumeration statesDeclaration
+ Property currentStateField
+ Map<State, EnumerationLiteral> stateEnumerators
+ Property historyTableDeclaration
+ Operation saveHistoryFunction
+ Map<Transition, OpaqueBehavior> actionChainFunctions
+ Map<Pseudostate, OpaqueBehavior> junctionPointFunctions
+ Map<Pseudostate, OpaqueBehavior> choicePointFunctions
+ Map<State, OpaqueBehavior> stateFunctions
+ Operation injectFunc
+ Operation initializeFunc
+ Stereotype refStereo
+ Stereotype constStereo
+
+ new() {
+ stateEnumerators = newHashMap
+ // userActionFunctions = newHashMap
+ actionChainFunctions = newHashMap
+ junctionPointFunctions = newHashMap
+ choicePointFunctions = newHashMap
+ stateFunctions = newHashMap
+ }
+
+ /**
+ * This is the main method of the transformation. It performs the
+ * transformation by invoking methods that generate each part of the
+ * target language model.
+ */
+ def transform(StateMachine m) {
+ machine = m
+ clazz = m.owner as Class
+
+ generateStatesDeclaration
+ generateCurrentStateField
+ generateHistoryTableDeclaration
+ generateSaveHistoryFunction
+ // generateAllUserActionFunctions
+ generateAllActionChainFunctions
+ generateAllJunctionFunctions
+ generateAllChoicePointFunctions
+ generateAllStateFunctions
+ generateInjectFunc
+ generateInitializeFunc
+ }
+
+ /**
+ * Builds an enum type for the states of the state machine.
+ *
+ * The generated code would be something like:
+ *
+ * <p><pre>
+ * <code>enum State { s0, s1, s1_s0, s1_s1, s2, ... };</code>
+ * </pre>
+ */
+ def generateStatesDeclaration() {
+
+ val clazz = machine.owner as Class
+ statesDeclaration = clazz.createNestedClassifier(GlobalConstants.STATE_TYPE_NAME,
+ UMLPackage.eINSTANCE.getEnumeration) as Enumeration
+ for (s : machine.states) {
+ if (s.name == null) {
+ s.name = "undefined"
+ }
+ val stateLiteral = statesDeclaration.createOwnedLiteral(s.name)
+ stateEnumerators.put(s, stateLiteral)
+ }
+ statesDeclaration.createOwnedLiteral(GlobalConstants.UNVISITED)
+
+ // stateEnumerators.put(State.UNVISITED, unvisitedStateLiteral)
+ }
+
+ /**
+ * Generates a field to hold the current state.
+ *
+ * The generated code would be something like:
+-- *
+ * <p><pre>
+ * <code>
+ * State currentState;
+ * </code>
+ * </pre>
+ */
+ def generateCurrentStateField() {
+ currentStateField = clazz.createOwnedAttribute(GlobalConstants.CURRENT_STATE_FIELD_NAME, statesDeclaration)
+ }
+
+ /**
+ * Generates a declaration for the history table for the state machine.
+ *
+ * The generated code would be something like:
+ *
+ * <p>
+ * <code>State[] history = { UNDEFINED, ..., UNDEFINED };
+ */
+ def generateHistoryTableDeclaration() {
+
+ // TODO: currentStateField already used (probably wrong!)
+ historyTableDeclaration = clazz.createOwnedAttribute(GlobalConstants.HISTORY_TABLE_NAME, statesDeclaration)
+ val numStates = machine.states.size
+
+ // use CppArray instead?
+ // TODO
+ // currentStateField.upper = numStates
+
+ // get constructor TODO
+ var ctor = clazz.getOwnedOperation(clazz.getName(), null, null)
+ var OpaqueBehavior ctorOB
+ if (ctor != null) {
+ ctorOB = ctor.methods.get(0) as OpaqueBehavior
+ }
+ if (ctor == null) {
+ ctor = clazz.createOperation(clazz.getName(), null)
+ ctorOB = clazz.createOpaqueBehavior(ctor)
+ }
+
+ // TODO: might be more than one constructor
+ ctorOB.set('''
+ int i = 0;
+ while (i<«numStates») {
+ «GlobalConstants.HISTORY_TABLE_NAME»[i++] = «GlobalConstants.UNVISITED»;
+ }''')
+ }
+
+ /**
+ * Generates a function that saves history.
+ *
+ * The code generated is as follows:
+ *
+ * <p><pre>
+ * <code>
+ * void saveHistory(State compositeState, State subState) {
+ * history[compositeState] = subState;
+ * }
+ * <code>
+ * </pre>
+ *
+ * where <code>State</code> is the capsule's state type (an enum) and
+ * <code>history</code> is the capsule's history table.
+ *
+ * <p><b>Note:</b> The current implementation generates this as a normal
+ * function but it should be either a macro or an inline function.
+ * However the C/C++ language model does not currently support these.
+ *
+ * @see
+ * #generateStatesDeclaration
+ * #generateHistoryTableDeclaration
+ */
+ def generateSaveHistoryFunction() {
+
+ // Create the operation programmatically. Yet, it would be better
+ // to provide a model template for this
+ // [LW container-transformation
+ // saveHist(State compositeState, State subState) {
+ // historyTable[param1] = param2;
+ // }
+ saveHistoryFunction = clazz.createOwnedOperation(GlobalConstants.SAVE_HISTORY_FUNC_NAME, null, null)
+ saveHistoryFunction.createOwnedParameter("compositeState", stateType)
+ saveHistoryFunction.createOwnedParameter("subState", stateType)
+ // behavior might exist already (created by flattener)
+ var funcOB = clazz.getOwnedBehavior(GlobalConstants.SAVE_HISTORY_FUNC_NAME)
+ if (funcOB == null) {
+ funcOB = clazz.createOpaqueBehavior(saveHistoryFunction)
+ }
+ else {
+ funcOB.specification = saveHistoryFunction
+ }
+ funcOB.set("history[compositeState] = subState;")
+ }
+
+ /**
+ * Generate function declarations for transition action chains.
+ *
+ * <p>Each function generated will have a sequence of calls, invoking either
+ * the action functions generated by {@link generateActionFunc} for
+ * transition, state entry and state exit actions, as well as invoking
+ * "save history" actions produced by the flattening transformation.
+ */
+ def generateAllActionChainFunctions() {
+ for (t : machine.region.transitions) {
+ val f = generateActionFunc(t)
+ actionChainFunctions.put(t, f)
+ }
+ }
+
+ /**
+ * Generates the function declaration for a single action chain.
+ */
+ def generateActionFunc(Transition t) {
+ val transitionFuncName = GlobalConstants.TRANS_ACTION_FUNC_PREFIX + "__" + t.name
+ val transitionFunc = clazz.createOwnedOperation(transitionFuncName, null, null)
+ transitionFunc.createRTMessageParam(GlobalConstants.CHAIN_FUNC_PARAM)
+ var transitionFuncOB = t.effect
+ if (transitionFuncOB == null) {
+ transitionFuncOB = clazz.createOpaqueBehavior(transitionFunc);
+ }
+ else {
+ transitionFuncOB.specification = transitionFunc
+ clazz.ownedBehaviors.add(transitionFuncOB)
+ }
+
+ val chainFuncName = GlobalConstants.ACTION_FUNC_PREFIX + "__" + t.name
+ val chainFunc = clazz.createOwnedOperation(chainFuncName, null, null)
+ chainFunc.createRTMessageParam(GlobalConstants.CHAIN_FUNC_PARAM)
+ val chainFuncOB = clazz.createOpaqueBehavior(chainFunc);
+
+ // now examine chain (separate function generateActionInvocation in original code)
+ // Generates a call to an action, either user action or action generated by
+ // the transformation.
+ var code = ""
+ for (action : t.chain.actions) {
+ code += call(action.specification, action.callParams)
+ }
+ chainFuncOB.set(code)
+ return chainFuncOB as OpaqueBehavior
+ }
+
+ // def Enumerator getEnum(CppEnum enum1, String string) {
+ // throw new UnsupportedOperationException("TODO: auto-generated method stub")
+ // }
+ /**
+ * Generates all functions corresponding to choice points.
+ */
+ def generateAllChoicePointFunctions() {
+ for (c : machine.region.choicePoints) {
+ val f = generateChoiceFunc(c)
+ choicePointFunctions.put(c, f)
+ }
+ }
+
+ /**
+ * Generates the function corresponding to a given choice point.
+ */
+ def generateChoiceFunc(Pseudostate p) {
+ val funcName = GlobalConstants.CHOICE_FUNC_PREFIX + p.name
+ val funcDecl = clazz.createOperation(funcName, null)
+ val param = funcDecl.createRTMessageParam(GlobalConstants.CHOICE_FUNC_PARAM)
+ val funcDeclOB = clazz.createOpaqueBehavior(funcDecl)
+
+ // if (generateGuard) { [actFunc/](param); [DestStatement]
+ var code = ""
+ for (t : p.outgoings) {
+ code += '''
+ if («t.guard.body») {
+ «call(actionChainFunctions.get(t), param.name)»
+ // TODO: return instead
+ «currentStateField.name» = «getDestination(t, false)»;
+ }
+ '''
+ }
+ funcDeclOB.set(code)
+ return funcDeclOB
+ }
+
+ /**
+ * Generates all functions corresponding to junction points.
+ */
+ def generateAllJunctionFunctions() {
+ for (j : machine.region.junctionPoints) {
+ val f = generateJunctionFunc(j)
+ junctionPointFunctions.put(j, f)
+ }
+ }
+
+ /**
+ * Generates the function corresponding to a specific junction point.
+ */
+ def generateJunctionFunc(
+ Pseudostate p
+ ) {
+ val funcName = GlobalConstants.JUNCTION_FUNC_PREFIX + p.name
+ val funcDecl = clazz.createOperation(funcName, null)
+ val funcDeclOB = clazz.createOpaqueBehavior(funcDecl)
+ funcDecl.createRTMessageParam(GlobalConstants.JUNC_FUNC_PARAM)
+ val t = p.outgoings.get(0) // There should be only one.
+ var code = ""
+ if (t != null) {
+ val actFunc = actionChainFunctions.get(t)
+ code += call(actFunc, GlobalConstants.JUNC_FUNC_PARAM)
+ }
+ code += getDestination(t, false)
+ funcDeclOB.set(code)
+ funcDeclOB
+ }
+
+ /**
+ * Generates all functions corresponding to states.
+ */
+ def generateAllStateFunctions() {
+ for (s : machine.states) {
+ val f = generateStateFunc(s)
+ stateFunctions.put(s, f)
+ }
+ }
+
+ /**
+ * Generates the function corresponding to a given state.
+ */
+ def generateStateFunc(State state) {
+ val name = GlobalConstants.STATE_FUNC_PREFIX + state.name
+ val retType = statesDeclaration
+ val func = clazz.createOperation(name, retType)
+ val param = func.createRTMessageParam(GlobalConstants.STATE_FUNC_PARAM)
+ val funcOB = clazz.createOpaqueBehavior(func)
+ val table = getPortTransitionsTable(state)
+
+ val code = '''
+ switch («getPortCond(param)») {
+ «FOR port : table.keySet»
+ case «enumeratorFor(port)»:
+ switch(«getSigCond(param)») {
+ «FOR t : table.get(port)»
+ «FOR trigger : t.triggers.filter[it.ports.contains(port)]»
+ case «enumeratorFor(trigger.event as CallEvent)»:
+ «IF (t.guard != null)»if (t.guard) { «ENDIF»
+ «actionChainFunctions.get(t).name»(«param.name»);
+ return «getDestination(t, false)»;
+ «IF (t.guard != null)»}«ENDIF»
+ «ENDFOR»
+ «ENDFOR»
+ }
+ «ENDFOR»
+ }
+ '''
+ funcOB.set(code)
+ funcOB
+ }
+
+ /**
+ * Builds a table that contains for each port, all the outgoing transitions
+ * of a given state whose trigger has that port.
+ *
+ * @param s a {@link State}
+ * @return a table T indexed by {@link Port}s such that for each port p, the
+ * entry T[p] contains all outgoing {@link Transition}s from s
+ * whose trigger has port p.
+ */
+ private def getPortTransitionsTable(State s) {
+ val table = newHashMap
+ for (t : s.outgoings) {
+ for (trigger : t.triggers) {
+ for (p : trigger.ports) {
+ if (!table.containsKey(p)) {
+ table.put(p, newHashSet)
+ }
+ table.get(p).add(t)
+ }
+ }
+ }
+ return table
+ }
+
+ /**
+ * Obtains the function call corresponding to a transition's destination.
+ *
+ * @param t - The {@link Transition}
+ * @param init - Whether we are looking for the destination to be obtained
+ * in the ized method or in the inject method.
+ */
+ private def getDestination(Transition t, boolean init) {
+ var String retVal
+ if (t.target instanceof Pseudostate) {
+ val ps = t.target as Pseudostate
+ if (ps.kind == PseudostateKind.CHOICE_LITERAL) {
+ val func = choicePointFunctions.get(ps)
+ retVal = func.getName() + "();"
+ } else if (ps.kind == PseudostateKind.JUNCTION_LITERAL) {
+ val func = junctionPointFunctions.get(ps)
+ retVal = func.getName() + "();"
+ }
+ } else {
+ retVal = stateEnumerators.get(t.target).name
+ }
+ if (init) {
+ // currentStateField = << code >>
+ retVal = '''«currentStateField.name» = «retVal»;'''
+ }
+ retVal
+ }
+
+ /**
+ * Generates the main 'inject' function that receives and handles events.
+ */
+ def generateInjectFunc() {
+ injectFunc = clazz.createOperation(GlobalConstants.INJECT_FUNC_NAME, null)
+
+ // injectFunc.setVirtual()
+ injectFunc.createRTMessageParam(GlobalConstants.INJECT_FUNC_PARAM)
+ val injectFuncOB = clazz.createOpaqueBehavior(injectFunc)
+ val code = '''
+ switch(stateCond) {
+ «FOR s : machine.states»
+ case «enumFor(s)»:
+ «currentStateField.name» = «call(stateFunctions.get(s), GlobalConstants.INJECT_FUNC_PARAM)»
+ break;
+ «ENDFOR»
+ }
+ '''
+ injectFuncOB.set(code)
+ injectFunc
+ }
+
+
+ /**
+ * Build the initialize function which performs the initial transition.
+ *
+ * <p>This assumes that the top level of the state machine must have an
+ * initial pseudo-state, and that there is exactly one outgoing transition
+ * from such initial point.
+ *
+ * <p> If there is no initial point, the body of the initialize method is
+ * empty.
+ */
+ def generateInitializeFunc() {
+ initializeFunc = clazz.createOperation(GlobalConstants.INITIALIZE_FUNC_NAME, null)
+
+ // initializeFunc.setVirtual()
+ initializeFunc.createRTMessageParam(GlobalConstants.INITIALIZE_FUNC_PARAM)
+ val initializeFuncOB = clazz.createOpaqueBehavior(initializeFunc)
+
+ var code = ""
+ if (machine.region.initialState != null) {
+ val initialTransition = machine.region.initialState.outgoings.get(0);
+ if (initialTransition != null) {
+ val actFunc = actionChainFunctions.get(initialTransition)
+ if (actFunc != null) {
+ code += call(actFunc, GlobalConstants.INITIALIZE_FUNC_PARAM)
+ }
+ }
+ code += getDestination(initialTransition, true)
+ initializeFuncOB.set(code)
+ }
+ }
+
+ def call(NamedElement fct, String param) '''
+ «fct.name»(«param»);
+ '''
+
+ def call(NamedElement fct, List<String> params) '''
+ «IF params != null»
+ «fct.name»(«FOR param : params SEPARATOR ', '»«param»«ENDFOR»);
+ «ELSE»
+ «fct.name»();
+ «ENDIF»
+ '''
+
+ /**
+ * Generates the compilation unit for the state machine (*)
+ *
+ * <p><b>Notes:</b> This implementation generates only a list of elements
+ * to be consumed by the capsule generator which is assumed to be
+ * responsible for putting together the full compilation unit.
+ */
+ /*
+ def generateCompilationUnit() {
+ // already added?
+
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, statesDeclaration);
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, currentStateField)
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, historyTableDeclaration)
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, saveHistoryFunction)
+ for (action : userActionFunctions.keySet) {
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, userActionFunctions.get(action))
+ }
+ for (chain : actionChainFunctions.keySet) {
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, actionChainFunctions.get(chain))
+ }
+ for (junction : junctionPointFunctions.keySet) {
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, junctionPointFunctions.get(junction))
+ }
+ for (choice : choicePointFunctions.keySet) {
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, choicePointFunctions.get(choice))
+ }
+ for (state : stateFunctions.keySet) {
+ cppCapsuleClass.addMember(CppClass.Visibility.PRIVATE, stateFunctions.get(state))
+ }
+
+ return generatedModel
+ }
+ */
+ /**
+ * Auxiliary methods
+ */
+ private def getStateType() {
+ statesDeclaration
+ }
+
+ private def getRTMessageType() {
+ // TODO: import umlrts instead of declaring it in model
+ val umlrts = clazz.getModel().getPackagedElement("umlrts") as org.eclipse.uml2.uml.Package
+ umlrts.getPackagedElement("RTMessage") as org.eclipse.uml2.uml.Type;
+ }
+
+ private def createRTMessageParam(Operation operation, String paramName) {
+ val param = operation.createOwnedParameter(paramName, RTMessageType)
+ if (refStereo == null) {
+ refStereo = param.getApplicableStereotype("C_Cpp::Ref")
+ }
+ if (refStereo != null) {
+ param.applyStereotype(refStereo)
+ }
+ if (constStereo == null) {
+ constStereo = param.getApplicableStereotype("C_Cpp::Const")
+ }
+ if (constStereo != null) {
+ param.applyStereotype(constStereo)
+ }
+ param
+ }
+
+ // TODO - why not used any more?
+ private def getRTDataType(Transition t) {
+ var Type rtdataType = null
+ val Collection<Type> types = newHashSet
+ for (trigger : t.triggers) {
+ val evt = trigger.event as CallEvent
+ val params = evt.operation.ownedParameters
+ if (! params.empty) {
+ val first = params.get(0)
+ types.add(first.type)
+ }
+ }
+ if (types.size == 1) {
+ val type = types.get(0)
+ // TODO - was - createType
+ rtdataType = type
+ }
+ rtdataType
+ }
+
+ private def enumFor(State s) {
+ stateEnumerators.get(s).label
+ }
+
+ private def dispatch enumeratorFor(Port port) {
+ val enumerator = EnumService.literal('PortID', port.name)
+ enumerator
+ }
+
+ private def dispatch enumeratorFor(CallEvent ce) {
+ val operation = ce.operation
+ val protocolCls = EnumService.literal('ProtocolClass', (operation.getInterface().owner as NamedElement).name);
+ '''«protocolCls»::signal_«ce.name»'''
+ }
+
+ /**
+ * Builds an expression to obtain the port enum id for the switch.
+ *
+ * <p>It assumes that the message parameter to the inject function is a
+ * pointer to the RTMessage type, as returned by {@link #getRTMessageType},
+ * this is, the signature of the inject function must be:
+ *
+ * <p><pre>
+ * <code>void inject(UMLRTMessage * msg)</code>
+ * </pre>
+ *
+ * <p>It also assumes that the port id and signal id are accessible from
+ * this type. Basically the assumption is that the relevant definitions are
+ * as follows:
+ *
+ * <p>
+ * <pre>
+ * <code>
+ * class UMLRTMessage : ... {
+ * public:
+ * UMLRTPort * destPort;
+ * UMLRTSignal * signal;
+ * }
+ *
+ * struct UMLRTPort {
+ * int id;
+ * // ...
+ * }
+ *
+ * class UMLRTSignal {
+ * public:
+ * int id;
+ * // ...
+ * }
+ * </code>
+ * </pre>
+ *
+ * <p>... where the typed <code>UMLRTPortId</code> and
+ * <code>UMLRTSignalId</code> can be cast to the <code>Port</code> and
+ * <code>Signal</code> enum types generated in the state machine's class.
+ *
+ * <p>Given this assumptions, the port condition generated has the form:
+ *
+ * <p><pre><code>(Port)(msg->destPort)->id</code></pre>
+ *
+ * <p>and the signal condition is:
+ *
+ * <p><pre><code>(ProtocolX::Signal)(msg->signal)->getId()</code></pre>
+ *
+ * <p>where <code>ProtocolX</code> is the name of the port's protocol
+ */
+ private def getPortCond(Parameter param) {
+ //val messagePortField = UMLRTMessage.destPort()
+ //val portIdField = UMLRTCommsPort.id()
+ //'''«param.name».«messagePortField.name»->«portIdField.name»'''
+ '''TODO'''
+ }
+
+ private def getSigCond(Parameter param) {
+ //val messageSignalField = UMLRTMessage.signal()
+ //val signalIdAccessor = UMLRTSignal.getId()
+ //'''«param.name»->«messageSignalField.name»->«signalIdAccessor.name»()'''
+ '''TODO'''
+ }
+}
diff --git a/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlattener.xtend b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlattener.xtend
new file mode 100644
index 00000000000..002469ae5b0
--- /dev/null
+++ b/extraplugins/qompass/designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/xtend/UMLFlattener.xtend
@@ -0,0 +1,556 @@
+/*******************************************************************************
+* Copyright (c) 2014 Zeligsoft, CEA and others.
+* 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
+*******************************************************************************/
+package org.eclipse.papyrus.qompass.modellibs.core.xtend
+
+import org.eclipse.uml2.uml.Behavior
+import org.eclipse.uml2.uml.Class
+import org.eclipse.uml2.uml.NamedElement
+import org.eclipse.uml2.uml.Pseudostate
+import org.eclipse.uml2.uml.PseudostateKind
+import org.eclipse.uml2.uml.Region
+import org.eclipse.uml2.uml.State
+import org.eclipse.uml2.uml.StateMachine
+import org.eclipse.uml2.uml.Transition
+import org.eclipse.uml2.uml.UMLPackage
+import org.eclipse.uml2.uml.Vertex
+
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.BehaviorUtil.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.StateMachineUtil.*
+import static extension org.eclipse.papyrus.qompass.modellibs.core.xtend.UMLChain.chain
+import org.eclipse.uml2.uml.OpaqueBehavior
+
+/**
+ * This class contains the transformation for flattening UML-RT state machines
+ *
+ * It implements the algorithms described in the technical report
+ *
+ * E. Posse. "Flattening UML-RT State Machines".
+ * Technical Report ZTR-2014-EP-001, Version 2, Zeligsoft, Sep 2014.
+ *
+ * @author eposse
+ */
+class UMLFlattener {
+
+ val FRESH_NAME_PREFIX = "p"
+ val FRESH_ENTRYPOINT_NAME_PREFIX = "entrypoint_"
+ val FRESH_EXITPOINT_NAME_PREFIX = "exitpoint_"
+ val FRESH_CHOICEPOINT_NAME_PREFIX = "c"
+ val FRESH_JUNCTIONPOINT_NAME_PREFIX = "j"
+ var FRESH_TRANSITION_NAME_PREFIX = "transition_"
+
+ var freshNameCounter = 0
+ var freshEntryPointNameCounter = 0
+ var freshExitPointNameCounter = 0
+ var freshChoicePointNameCounter = 0
+ var freshJunctionPointNameCounter = 0
+ var freshTransitionNameCounter = 0
+
+ var Behavior saveHistoryBehavior = null
+ var Class clazz
+
+ /**
+ * Flattens a UML-RT state machine, removing composite states, and making
+ * explicit transitions implied by group transitions, history points and
+ * initial points.
+ *
+ * This is the 'main' method of the transformer. It performs the
+ * transformation in-place.
+ *
+ * @param m a {@link StateMachine}
+ * @return the flat {@link StateMachine} m with all composite states, group
+ * transitions, history and initial pseudo-states removed.
+ */
+ def StateMachine transform(StateMachine m) {
+ var StateMachine intermediateModel
+ clazz = m.owner as Class
+ UMLChain.initChains
+ phase0QualifyNames(m.region, m.name)
+ phase1(m)
+ intermediateModel = phase2(m)
+ return intermediateModel
+ }
+
+ /**
+ * Change the names of states and transitions: prefix them with the names
+ * of the stateMachine and composite states.
+ */
+ protected def void phase0QualifyNames(Region region, String parentName) {
+ for (Transition transition : region.transitions) {
+ transition.name = parentName + '_' + transition.name
+ }
+ for (Vertex vertex : region.subvertices) {
+ vertex.name = parentName + '_' + vertex.name
+ if (vertex instanceof State) {
+ val State state = vertex as State
+ for (subRegion : state.regions) {
+ phase0QualifyNames(subRegion, vertex.name)
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Makes explicit transitions implied by group transitions, history points
+ * and initial points.
+ */
+ protected def StateMachine phase1(StateMachine m) {
+ for (State s : m.states) {
+ phase1ProcessState(s)
+ }
+ return m
+ }
+
+ def void phase1ProcessState(State state) {
+ phase1ProcessSimpleState(state)
+ if (!state.regions.empty) {
+ phase1ProcessCompositeState(state)
+ }
+ }
+
+ /**
+ * Moves a simple state's entry actions to its incoming transitions and
+ * the state's exit actions to its outgoing transitions.
+ *
+ */
+ def void phase1ProcessSimpleState(State state) {
+ // TODO: should that be done in UML2FlatBody (need chain?)
+ if (state.entry != null) {
+ val entryOp = clazz.createOperation(entryFctName(state), null);
+ state.entry.name = entryFctName(state)
+ // add specification
+ state.entry.specification = entryOp;
+ // clazz.ownedBehaviors.add(state.entry)
+ for (Transition t : state.incomings) {
+ t.chain.append(state.entry)
+ }
+ }
+ if (state.exit != null) {
+ val exitOp = clazz.createOperation(exitFctName(state), null);
+ state.exit.name = exitFctName(state)
+ // add specification
+ state.exit.specification = exitOp;
+ // clazz.ownedBehaviors.add(state.exit)
+ for (Transition t : state.allOutgoings) {
+ t.chain.prepend(state.exit)
+ }
+ }
+ }
+
+ def entryFctName(State state) {
+ GlobalConstants.ENTRY_ACTION_FUNC_PREFIX + GlobalConstants.FUNC_NAME_QUAL_NAME_SEP + state.name + GlobalConstants.FUNC_NAME_QUAL_NAME_SEP + state.entry.name
+ }
+
+ def exitFctName(State state) {
+ GlobalConstants.EXIT_ACTION_FUNC_PREFIX + GlobalConstants.FUNC_NAME_QUAL_NAME_SEP + state.name + GlobalConstants.FUNC_NAME_QUAL_NAME_SEP + state.exit.name
+ }
+
+ /**
+ * Creates entry transitions for incoming arrows ending at the composite
+ * state's boundary or history pseudo-state. Creates exit transitions
+ * implied by group transitions.
+ */
+ def void phase1ProcessCompositeState(State state) {
+
+ // if (state.substates.empty) {
+ // replaceBySimpleState(state)
+ // return
+ // }
+ // Deal with incoming transitions
+ // TODO (ar): such a state can have entry and exit as well, no?
+ annotateExplicitEntryTransitions(state)
+ createEntryPoints(state)
+ var historyChoicePoint = replaceHistoryPoint(state)
+ removeInitialTransition(state, historyChoicePoint)
+
+ // Deal with outgoing transitions
+ annotateExplicitExitTransitions(state)
+ createExitPoints(state)
+ createExitTransitions(state)
+
+ // Process sub-states
+ for (State subState : state.subStates) {
+ phase1ProcessState(subState)
+ }
+ }
+
+ /**
+ * Prepends the state's entry action to each explicit entry transition
+ * (transition from an entry point to a sub-state).
+ */
+ def annotateExplicitEntryTransitions(State state) {
+ for (Pseudostate p : state.entryPoints) {
+ if (!p.outgoings.empty) {
+ for (Transition t : p.outgoings) {
+ t.chain.append(state.entry)
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates entry points for every direct incoming transition (transition
+ * ending directly on the state's boundary).
+ */
+ def createEntryPoints(State state) {
+ for (Transition t : state.incomings) {
+ val p = state.createConnectionPoint(state.newFreshEntryPointName)
+ p.kind = PseudostateKind.ENTRY_POINT_LITERAL
+ t.target = p
+ } //TODO: maybe remove all directIncomming?
+ }
+
+ /**
+ * Replaces the (deep)history pseudo-state with a choice point with transitions
+ * to each sub-state with conditions checking the value of the history table
+ * entry for this composite-state.
+ */
+ def Pseudostate replaceHistoryPoint(State state) {
+
+ // transform history state into a choice point
+ val c = state.region.deepHistory;
+
+ if (c != null) {
+ // No need to redirect incoming transitions, since we transform the history
+ // state with a choice point
+ c.kind = PseudostateKind.CHOICE_LITERAL;
+ }
+ else {
+ return null;
+ }
+
+ // Create transitions from the choice point to each sub-state with the
+ // appropriate guard.
+ for (State subState : state.subStates) {
+ var Vertex targetVertex
+ if (subState.regions.size() == 0) {
+ targetVertex = subState
+ }
+ else {
+ targetVertex = subState.region.deepHistory
+ if (targetVertex == null) {
+ targetVertex = subState
+ }
+ }
+
+ val newTransition = state.region.createTransition(state.newFreshTransitionName)
+ newTransition.source = c;
+ newTransition.target = targetVertex;
+ val guard = newTransition.createGuard("CheckHistory");
+ guard.createOpaqueExpression('''history[«state.name»] == «subState.name»''')
+ if (state.entry != null) {
+ newTransition.chain.append(state.entry)
+ }
+ }
+ // If there was an initial pseudo-state, create a transition from the
+ // choice point to the initial state where the guard will be true if
+ // the composite state has not been visited before.
+ val initialState = state.region.initialState
+ if (initialState != null) {
+ val initialTransition = initialState.outgoings.get(0)
+
+ val newTransition = state.region.createTransition(state.newFreshTransitionName)
+ newTransition.source = c;
+ newTransition.target = initialTransition.target;
+ val guard = newTransition.createGuard("CheckHistory");
+ guard.createOpaqueExpression('''history[«state.name»] == «GlobalConstants.UNVISITED»''')
+ // TODO: not sure, if semantics is the same.
+ if (initialTransition.effect != null) {
+ // caveat: assigining the effect to the new transition will remove it from the original
+ // (initial will be removed later on => not a problem?)
+ newTransition.effect = initialTransition.effect;
+ newTransition.chain.append(newTransition.effect)
+ }
+ newTransition.chain.append(state.entry)
+ }
+ // If there was no initial pseudo-state, create a 'dummy' simple state
+ // representing "staying at the boundary", and create a transition from
+ // the choice point to this dummy state, where the guard is true if
+ // the state has not been visited before.
+ else {
+ // The name should be different name because one of the sub-states
+ // may have the same name as the composite.
+ val border = state.region.createState(state.newFreshName);
+
+ val newTransition = state.region.createTransition(state.newFreshTransitionName);
+ newTransition.source = c;
+ newTransition.target = border;
+ val guard = newTransition.createGuard("Check History")
+ guard.createOpaqueExpression('''history[«state.name»] == «GlobalConstants.UNVISITED»''')
+ if (state.entry != null) {
+ newTransition.chain.append(state.entry)
+ }
+ }
+ return c
+ }
+
+ /**
+ * Remove the initial pseudo-state and transition and create a transition
+ * from each entry point which does not have an explicit entry transition
+ * to a sub-state, to the initial state.
+ */
+ def removeInitialTransition(State state, Pseudostate historyChoicePoint) {
+ val initialState = state.region.initialState
+ if (initialState != null) {
+ val initialTransition = initialState.outgoings.get(0) // There should be exactly one initial transition
+ for (Pseudostate p : state.entryPoints) {
+ if (p.outgoings.empty) {
+ val newTransition =
+ state.region.createTransition(state.newFreshTransitionName)
+ newTransition.source = p
+ newTransition.target = initialTransition.target
+ newTransition.chain.append(state.entry)
+ newTransition.chain.append(initialTransition.effect);
+ }
+ }
+ state.region.transitions.remove(initialTransition)
+ // initialTransition.targetVertex.incomingTransitions.remove(initialTransition) // TODO: this might not be enough if the initial transition ends in a pseudo-state
+ // state.removeInitial
+ }
+ else {
+ for (Pseudostate p : state.entryPoints) {
+ if (p.outgoings.empty) {
+ val newTransition =
+ state.region.createTransition(state.newFreshTransitionName)
+ newTransition.setSource(p)
+ newTransition.setTarget(historyChoicePoint)
+ newTransition.effect = state.entry;
+ }
+ }
+ }
+ }
+
+ /**
+ * Annotate explicit exit transitions (transitions from a sub-state to an
+ * exit point) with a "history saving action", an action that sets the
+ * history table entry for the composite state according to the sub-state
+ * that is exited.
+ */
+ def annotateExplicitExitTransitions(State state) {
+ for (Pseudostate p : state.exitPoints) {
+ if (!p.incomings.empty) {
+ for (Transition t : p.incomings) {
+ if (saveHistoryBehavior == null) {
+ createSaveHistoryBehavior
+ }
+ // Actions can have specific subclasses in the Zeligsoft model. Here we use a single generic class.
+ // Therefore we add call information explicitly.
+ val UMLAction saveHistoryAction = new UMLAction(saveHistoryBehavior)
+ saveHistoryAction.addParam = state.name
+ saveHistoryAction.addParam = t.source.name
+ t.chain.append = saveHistoryAction
+ if (state.exit != null) {
+ t.chain.append(state.exit)
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create exit points for each direct outgoing transition (transition leaving
+ * directly from the composite state's boundary).
+ */
+ def createExitPoints(State state) {
+ for (Transition t : state.outgoings) {
+ val p = state.createConnectionPoint(state.newFreshExitPointName);
+ p.kind = PseudostateKind.EXIT_POINT_LITERAL
+ t.source = p;
+ }
+ }
+
+ def createSaveHistoryBehavior() {
+ // create an opaque behavior without body. This will be added later in the UMLFlat2Cpp operation
+ saveHistoryBehavior = clazz.createOwnedBehavior(GlobalConstants.SAVE_HISTORY_FUNC_NAME,
+ UMLPackage.eINSTANCE.getOpaqueBehavior()
+ );
+ }
+
+ /**
+ * Create explicit exit transitions implied by group transitions. For each
+ * group transition creates a transition from every sub-state to the
+ * group-transitions's source exit point. It annotates these transitions
+ * with a "history saving action", an action which stores the sub-state
+ * in the history table entry for this composite state.
+ */
+ def createExitTransitions(State state) {
+
+ // Iterate over exit points, looking for group transitions.
+ for (Pseudostate p : state.exitPoints) {
+
+ // If the exit point doesn't have incoming transitions then there
+ // is at least one group transition from it.
+ if (p.incomings.empty) {
+
+ // Create explicit transitions from every sub-state to this
+ // exit point...
+ for (State subState : state.subStates) {
+
+ // ...for each group transition leaving the exit point.
+ for (Transition t : p.outgoings) {
+
+ if (saveHistoryBehavior == null) {
+ createSaveHistoryBehavior
+ }
+ // Append the history saving action and the state's
+ // exit action.
+ val newTransition = state.region.createTransition(state.newFreshTransitionName)
+ newTransition.source = subState
+ newTransition.target = p
+ // make a copy (adding it to triggers list would remove it from original transition).
+ for (trigger : t.triggers) {
+ val newTrigger = newTransition.createTrigger(trigger.name)
+ newTrigger.event = trigger.event
+ }
+ // newTransition.triggers.addAll(t.triggers)
+ newTransition.guard = t.guard
+ val UMLAction saveHistoryAction = new UMLAction(saveHistoryBehavior)
+ saveHistoryAction.addParam = state.name
+ saveHistoryAction.addParam = subState.name
+ newTransition.chain.append(saveHistoryAction)
+ newTransition.chain.append(state.exit)
+ // make a copy of the effect (but: quite bad, since we might create several copies of same effect)
+ if (t.effect instanceof OpaqueBehavior) {
+ val newBehavior = newTransition.createOpaqueEffect
+ newBehavior.name = t.effect.name
+ newBehavior.set = t.effect.body
+ }
+ }
+ }
+
+ // Remove the trigger and guard from the old group transition,
+ // but leave the transition.
+ // TODO: we must replace the direct group transition with an indirect group transition leaving from the exit point
+ for (Transition t : p.outgoings) {
+ t.triggers.clear
+ t.guard = null
+ t.effect = null
+ }
+ }
+ }
+ }
+
+ /**
+ * Flatten composite states.
+ */
+ protected def StateMachine phase2(StateMachine m) {
+ for (State s : m.states.clone) {
+ phase2ProcessState(s)
+ if (!s.subStates.empty) {
+ m.region.moveContents(s)
+ // remove regions from composite state
+ s.regions.clear
+ }
+ }
+ return m
+ }
+
+ /**
+ * Removes entry and exit points of a simple state, making all transitions
+ * to and from it, direct.
+ */
+ def dispatch void phase2ProcessState(State state) {
+ if (state.regions.empty) {
+ phase2ProcessSimpleState(state)
+ }
+ else {
+ phase2ProcessComplexState(state)
+ }
+ // change name afterwards (avoid that new names are taken into account recursively)
+ }
+
+ /**
+ * Removes entry and exit points of a simple state, making all transitions
+ * to and from it, direct.
+ */
+ def dispatch void phase2ProcessSimpleState(State state) {
+ for (Transition t : state.indirectIncomings) {
+ t.target = state // TODO: Potential problem: depending on the set implementation we may be modifying the iterator
+ }
+ for (Transition t : state.outgoings) {
+ t.source = state
+ }
+ for (Pseudostate p : state.entryPoints) {
+ state.connectionPoints.remove(p)
+ }
+ for (Pseudostate p : state.exitPoints) {
+ state.connectionPoints.remove(p)
+ }
+ }
+
+ /**
+ * Replaces all entry and exit points of the composite state with junction
+ * points, and recursively apply this to sub-states.
+ */
+ def dispatch void phase2ProcessComplexState(State state) {
+ // Replace connection points with junction points
+ for (Pseudostate p : state.connectionPoints.clone) {
+ var j = state.region.createPseudostate(GlobalConstants.JUNCTION_FUNC_PREFIX + p.name)
+ j.kind = PseudostateKind.JUNCTION_LITERAL
+
+ for (Transition t : p.incomings) {
+ t.target = j
+ }
+ for (Transition t : p.outgoings) {
+ t.source = j
+ }
+ if (p.kind == PseudostateKind.ENTRY_POINT_LITERAL) {
+ state.connectionPoints.remove(p)
+ }
+ else if (p.kind == PseudostateKind.EXIT_POINT_LITERAL) {
+ state.connectionPoints.remove(p)
+ }
+ }
+
+ // Process substates
+ for (State subState : state.subStates.clone) {
+ phase2ProcessState(subState)
+ if (!subState.regions.empty) {
+ state.region.moveContents(subState)
+ subState.regions.clear
+ }
+ }
+ }
+
+ /**
+ * Auxiliary methods
+ */
+ def String getNewFreshName(NamedElement parent) {
+ freshNameCounter ++
+ return parent.namePrefix + FRESH_NAME_PREFIX + freshNameCounter
+ }
+
+ def String getNewFreshEntryPointName(NamedElement parent) {
+ freshEntryPointNameCounter ++
+ return parent.namePrefix + FRESH_ENTRYPOINT_NAME_PREFIX + freshEntryPointNameCounter
+ }
+
+ def String getNewFreshExitPointName(NamedElement parent) {
+ freshExitPointNameCounter ++
+ return parent.namePrefix + FRESH_EXITPOINT_NAME_PREFIX + freshExitPointNameCounter
+ }
+
+ def String getNewFreshChoicePointName(NamedElement parent) {
+ freshChoicePointNameCounter ++
+ return parent.namePrefix + FRESH_CHOICEPOINT_NAME_PREFIX + freshChoicePointNameCounter
+ }
+
+ def String getNewFreshJunctionPointName(NamedElement parent) {
+ freshJunctionPointNameCounter ++
+ return parent.namePrefix + FRESH_JUNCTIONPOINT_NAME_PREFIX + freshJunctionPointNameCounter
+ }
+
+ def String getNewFreshTransitionName(NamedElement parent) {
+ freshTransitionNameCounter ++
+ return parent.namePrefix + FRESH_TRANSITION_NAME_PREFIX + freshTransitionNameCounter
+ }
+
+ def namePrefix(NamedElement ne) {
+ return ne.name + "_"
+ }
+}

Back to the top