diff options
Diffstat (limited to 'extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core')
36 files changed, 619 insertions, 592 deletions
diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/.settings/org.eclipse.jdt.core.prefs b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..c537b63063c --- /dev/null +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/build.acceleo b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/build.acceleo index b4a22fdacc3..fee539f50f8 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/build.acceleo +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/build.acceleo @@ -18,7 +18,7 @@ <acceleoCompiler sourceFolder="${target.folder}" outputFolder="${target.folder}" - dependencies="${target.folder}/../../org.eclipse.papyrus.fcm.profile;${target.folder}/../../org.eclipse.papyrus.infra.core.sasheditor;${target.folder}/../../org.eclipse.papyrus.infra.core.sasheditor.di;${target.folder}/../../org.eclipse.papyrus.qompass.designer.vsl;${target.folder}/../../org.eclipse.papyrus.cpp.profile;${target.folder}/../../org.eclipse.papyrus.acceleo;${target.folder}/../../org.eclipse.papyrus.infra.widgets.toolbox;" + dependencies="${target.folder}/../../org.eclipse.papyrus.fcm.profile;${target.folder}/../../org.eclipse.papyrus.qompass.designer.vsl;${target.folder}/../../org.eclipse.papyrus.cpp.profile;${target.folder}/../../org.eclipse.papyrus.acceleo;${target.folder}/../../org.eclipse.papyrus.uml.tools.utils;" binaryResource="false" packagesToRegister=""> </acceleoCompiler> diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/ConnectorUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/ConnectorUtils.java deleted file mode 100644 index 10c88411a9f..00000000000 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/ConnectorUtils.java +++ /dev/null @@ -1,194 +0,0 @@ -/***************************************************************************** - * 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.designer.core; - -import org.eclipse.core.runtime.Status; -import org.eclipse.uml2.uml.Class; -import org.eclipse.uml2.uml.ConnectableElement; -import org.eclipse.uml2.uml.Connector; -import org.eclipse.uml2.uml.ConnectorEnd; -import org.eclipse.uml2.uml.Port; -import org.eclipse.uml2.uml.Property; - -public class ConnectorUtils { - - /** - * Returns true, is a port of a composite has an internal delegation to - * another port - * - * @param composite - * @param port - * @return - */ - public static boolean isDelegation(Class composite, Port port) { - return (getDelegation(composite, port) != null); - } - - /** - * Return the connector end of a delegation originating from a given port - * or null, if not such delegation exists - * - * @param composite - * the composite component - * @param port - * a port (may be inherited) of that implementation - * @return a connector end to which the port delegates or null - */ - public static ConnectorEnd getDelegation(Class composite, Port port) { - for(Connector connector : composite.getOwnedConnectors()) { - if(connectsPort(connector, port)) { - ConnectorEnd otherEnd = connEndNotPart(connector, null); - if(otherEnd != null) { - return otherEnd; - } - } - } - return null; - } - - /** - * check if a connector connects the port that is passed - * as parameter - * TODO: why is that name based??? - */ - public static boolean connectsPort(Connector connection, Port port) { - // check roles of end points - // String qPortName = port.getQualifiedName(); - for(ConnectorEnd end : connection.getEnds()) { - if(end.getRole() == port) { - return true; - } - if(end.getRole() != null) { - if(end.getRole() == port) { - Log.log(Status.ERROR, Log.TRAFO_CONNECTOR, - "ConnectorUtls.connectsPort: qualified names match, but not the ID - should not happen"); //$NON-NLS-1$ - return true; - } - } else { - Log.log(Status.ERROR, Log.TRAFO_CONNECTOR, - "ConnectorUtils.connectsPort: the role of one of the endpoints of connection " + connection.getName() + //$NON-NLS-1$ - " is null - should not happen"); //$NON-NLS-1$ - } - } - return false; - } - - /** - * Simple helper function: return a connector end that is referencing - * the passed parameter "part" either directly (role) or via a port - * - * @param part - * a property within a composite - * @param connection - * @return the first connector end that is referencing a certain part - * passed as parameter - */ - public static ConnectorEnd connEndForPart(Connector connection, Property part) { - // look for the end with same part (connectedPart == part) - for(ConnectorEnd end : connection.getEnds()) { - ConnectableElement role = end.getRole(); - Property connectedPart = null; - if(role instanceof Port) { - connectedPart = end.getPartWithPort(); - } else if(role instanceof Property) { - // role is not a Port but also not null => connected directly to a part - connectedPart = (Property)role; - } - - if(connectedPart == part) { - return end; - } - } - return null; - } - - /** - * Simple helper function: return a connector end that is *not* referencing - * with the passed parameter "part" either directly or via a port - * (useful, to get the "other" end of a connector). - * - * @param part - * a property within a composite - * @param connection - * @return the first connector end that is not referencing to the - * part passed as parameter. - */ - public static ConnectorEnd connEndNotPart(Connector connection, Property part) { - // look for the other end (connectedPart != part) - for(ConnectorEnd end : connection.getEnds()) { - ConnectableElement role = end.getRole(); - Property connectedPart = null; - - if(role instanceof Port) { - connectedPart = end.getPartWithPort(); - } else if(role instanceof Property) { - // role is not a Port but also not null => connected directly to a part - connectedPart = (Property)role; - } - - if(connectedPart != part) { - return end; - } - - } - return null; - } - - /** - * check if a connector connects the part that is passed - * as parameter - */ - public static boolean connectsPart(Connector connection, Property part) { - return (connEndForPart(connection, part) != null); - } - - /** - * Return true, if passed connector is an assembly connector - * - * @param connection - * @return true, if assembly connection - */ - public static boolean isAssembly(Connector connection) { - // no "null" part found => all ends are parts - return (connEndForPart(connection, null) == null); - } - - /** - * @param composite A composite class - * @param partA A part within the composite - * @param partB Another part within the composite - * @return a connector, if it connects the parts A and B could within the passed composite, or null if no - * such connector exists - */ - public static Connector getConnector(Class composite, Property partA, Property partB) { - for (Connector connector : composite.getOwnedConnectors()) { - if (ConnectorUtils.connectsPart(connector, partA) && ConnectorUtils.connectsPart(connector, partB)) { - return connector; - } - } - return null; - } - - /** - * @param composite A composite class - * @param partA A part within the composite - * @param partB Another part within the composite - * @return true, if a connector between the parts A and B could be - * found within the passed composite - */ - public static boolean existsConnector(Class composite, Property partA, Property partB) { - return getConnector(composite, partA, partB) != null; - } -} diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Messages.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Messages.java index 8f0a90b7f06..0c0ffb0092f 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Messages.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Messages.java @@ -7,11 +7,15 @@ public class Messages extends NLS { public static String BootLoaderGen_AtLeastOneBlockingCall; + public static String BootLoaderGen_CannotApplyCppInclude; + public static String BootLoaderGen_CannotRetrieveTemplate; public static String CommandSupport_NoEditingDomain; public static String CommandSupport_ErrorDuringCmdExec; public static String ConfigUtils_RuleWithoutBaseClass; + public static String DepCreation_SingletonExistsAlready; + public static String DepCreation_CannotFindImplementation; public static String DepCreation_CircularReference; @@ -74,7 +78,11 @@ public class Messages extends NLS { public static String ContainerTrafo_CannotApplyRule; public static String ContainerTrafo_CannotFindDelegationConn; public static String ContainerTrafo_InterceptionRuleButNoInterceptor; + + public static String ContainerTrafo_RecursiveLWnotSupported; + public static String InstanceConfigurator_InvalidPluginExtension; + public static String InstantiateDepPlan_AcceleoErrors; public static String InstantiateDepPlan_AcceleoErrorsCheckLog; public static String InstantiateDepPlan_CannotGenModel; diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/PortUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/PortUtils.java index 8679e1f830b..e6ff1cb5bd8 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/PortUtils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/PortUtils.java @@ -247,10 +247,10 @@ public class PortUtils { */ public static boolean matches(Port portA, Port portB, boolean isAssembly) { if(isAssembly) { - return (sameKinds(portA, portB) && (portA.isConjugated() != portB.isConjugated())); + return ((portA.getType() == portB.getType()) && sameKinds(portA, portB) && (portA.isConjugated() != portB.isConjugated())); } else { // delegation - return (sameKinds(portA, portB) && (portA.isConjugated() == portB.isConjugated())); + return ((portA.getType() == portB.getType()) && sameKinds(portA, portB) && (portA.isConjugated() == portB.isConjugated())); } } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Utils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Utils.java index 2fac99cac7b..e179fb22924 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Utils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/Utils.java @@ -19,20 +19,16 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Iterator; -import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.runtime.FileLocator; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.UniqueEList; import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.papyrus.FCM.Assembly; import org.eclipse.papyrus.FCM.ContainerRule; import org.eclipse.papyrus.FCM.RuleApplication; import org.eclipse.papyrus.FCM.Singleton; -import org.eclipse.papyrus.infra.core.services.ServiceException; -import org.eclipse.papyrus.infra.emf.utils.ServiceUtilsForHandlers; import org.eclipse.papyrus.qompass.designer.core.preferences.QompassPreferenceConstants; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; import org.eclipse.uml2.uml.AggregationKind; @@ -363,36 +359,6 @@ public class Utils { } /** - * Return the top element of the model that is currently edited. This function is based on the - * assumption that the user model is the first resource that is loaded into the model set. - * Use this function instead of Utils.getTop (or getModel) if you want to avoid navigating to the - * root of an imported model. - * - * @return the top level package of the model currently loaded into an editor. - */ - public static Package getUserModel(ExecutionEvent event) { - ServiceUtilsForHandlers serviceUtils = ServiceUtilsForHandlers.getInstance(); - try { - // IPath fn = serviceUtils.getModelSet().getFilenameWithoutExtension(); - EList<Resource> resources = serviceUtils.getModelSet(event).getResources(); - if(resources.size() >= 3) { - // check first three resources (di, notation, uml) - for(int i = 0; i < 3; i++) { - Resource userResource = resources.get(i); - if(userResource.getContents().size() > 0) { - EObject topEObj = userResource.getContents().get(0); - if(topEObj instanceof Package) { - return (Package)topEObj; - } - } - } - } - } catch (ServiceException e) { - } - return null; - } - - /** * @param a * potential implementation * @return true, if passed classifier is an implementation (i.e. declared diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/EnumService.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/EnumService.java index 2870684a147..e1e5d8eb9a0 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/EnumService.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/EnumService.java @@ -73,9 +73,11 @@ public class EnumService { } /** - * Create a literal within an enumeration. Both, the literal and the enumeration may be an Acceleo template startiung with [ - * - * @param dummy + * Create a literal within an enumeration. Both, the literal and the enumeration may be an + * Acceleo template. If the name of the enumeration starts with "L", it is considered as a + * local enumeration, i.e. a nested classifier within the classifier (it has to be a class) + * from the transformation context. + * * @param enumName * the name of an enumeration * @param literal @@ -83,23 +85,6 @@ public class EnumService { * @return */ public static String literal(String enumName, String literal) { - // Acceleo does not expand parameters, so we do it here - /* - * if(enumName.contains("[") && enumName.contains("/]")) { - * try { - * enumName = AcceleoDriver.bind(enumName, dummy); - * } catch (TransformationException e) { - * return e.toString(); - * } - * } - * if(literal.contains("[") && enumName.contains("/]")) { - * try { - * literal = AcceleoDriver.bind(literal, dummy); - * } catch (TransformationException e) { - * return e.toString(); - * } - * } - */ Enumeration enumeration = enumHash.get(enumName); if(enumPkg == null) { return literal; @@ -121,9 +106,21 @@ public class EnumService { // declare a dependency to the enumeration from the current classifier checkAndCreateDependency(TransformationContext.classifier, enumeration); - return literal; + if (enumName.startsWith("L")) { //$NON-NLS-1$ + return literal; + } + else { + return GLOBALENUMS + "::" + literal; //$NON-NLS-1$ + } } + /** + * Create a dependency between the passed classifier, target pair. The objective + * of this function is that code generators do the necessary to assure that the + * target is known within the classifier (e.g. include directives) + * @param classifier a classifier + * @param target a target, on which the classifier or its code depends. + */ public static void checkAndCreateDependency(Classifier classifier, NamedElement target) { boolean found = false; for(Dependency dep : classifier.getClientDependencies()) { @@ -132,7 +129,8 @@ public class EnumService { } } if(!found) { - classifier.createDependency(target); + Dependency dep = classifier.createDependency(target); + dep.setName(String.format("from %s to %s", classifier.getName(), target.getName())); //$NON-NLS-1$ } } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/UMLTool.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/UMLTool.java index d63fd1b3655..64b2513dabd 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/UMLTool.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/acceleo/UMLTool.java @@ -25,6 +25,7 @@ import org.eclipse.papyrus.C_Cpp.External; import org.eclipse.papyrus.C_Cpp.NoCodeGen; import org.eclipse.papyrus.C_Cpp.Typedef; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; +import org.eclipse.uml2.uml.BehavioredClassifier; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Dependency; @@ -259,14 +260,15 @@ public class UMLTool { * The operation is useful in the context of state-machines: when a transition is triggered by * the call of an operation of the class, we'd like to know which interceptor (for which interface) * belongs to it (since the operations are enumerated within each interface). - * TOOD: move operation into state-chart java code + * TODO: move operation into state-chart java code + * TODO: would not work for ROOM ports typed with a collaboration * * @param operation * @return the interface which the operation belongs */ public static Interface implementsInterface(Operation operation) { Element owner = operation.getOwner(); - if(owner instanceof Class) { + if(owner instanceof BehavioredClassifier) { String name = operation.getName(); EList<Type> types = new BasicEList<Type>(); for(Parameter parameter : operation.getOwnedParameters()) { @@ -275,7 +277,7 @@ public class UMLTool { // loop over implemented realizations. Do not rely on FCM derivedElement information // as it might be missing on some models (it would point from an operation of the class // to the associated operation of the interface) - for(InterfaceRealization ir : ((Class)owner).getInterfaceRealizations()) { + for(InterfaceRealization ir : ((BehavioredClassifier)owner).getInterfaceRealizations()) { // check for types to allow for overloading Operation candidate = ir.getContract().getOwnedOperation(name, null, types); if(candidate != null) { diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/AllocUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/AllocUtils.java index ef288caaf17..770c7246a06 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/AllocUtils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/AllocUtils.java @@ -22,9 +22,9 @@ import org.eclipse.emf.common.util.UniqueEList; import org.eclipse.papyrus.FCM.Fragment; import org.eclipse.papyrus.MARTE.MARTE_DesignModel.SRM.SW_Concurrency.SwSchedulableResource; import org.eclipse.papyrus.MARTE.MARTE_Foundations.Alloc.Allocate; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Log; import org.eclipse.papyrus.qompass.designer.core.Utils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; import org.eclipse.uml2.uml.Abstraction; import org.eclipse.uml2.uml.Class; @@ -58,8 +58,13 @@ public class AllocUtils { */ public static EList<InstanceSpecification> getAllNodes(InstanceSpecification instance) { EList<InstanceSpecification> nodeList = getNodes(instance); - for(InstanceSpecification containedInstance : DepUtils.getContainedInstances(instance)) { - nodeList.addAll(getAllNodes(containedInstance)); + for(Slot slot : instance.getSlots()) { + if (!DepUtils.isShared(slot)) { + InstanceSpecification containedInstance = DepUtils.getInstance(slot); + if (containedInstance != null) { + nodeList.addAll(getAllNodes(containedInstance)); + } + } } return nodeList; } @@ -237,12 +242,12 @@ public class AllocUtils { for(Connector connection : compositeCL.getOwnedConnectors()) { // is one connector end targeted at the containedProperty ? - ConnectorEnd end = ConnectorUtils.connEndForPart(connection, containedProperty); + ConnectorEnd end = ConnectorUtil.connEndForPart(connection, containedProperty); if(end == null) continue; // does the connector at the same connect the composite's port? - if(ConnectorUtils.connectsPort(connection, port)) { + if(ConnectorUtil.connectsPort(connection, port)) { Port containedPort = (Port)end.getRole(); nodeList.addAll(getAllNodesForPort(DepUtils.getInstance(slot), containedPort)); } @@ -310,11 +315,11 @@ public class AllocUtils { */ } for(Connector connection : compositeCL.getOwnedConnectors()) { - if(ConnectorUtils.connectsPort(connection, port)) { + if(ConnectorUtil.connectsPort(connection, port)) { Log.log(Status.INFO, Log.TRAFO_CONNECTOR, "connector: " + connection.getName()); //$NON-NLS-1$ Log.log(Status.INFO, Log.TRAFO_CONNECTOR, "end1: " + connection.getEnds().get(0).getPartWithPort()); //$NON-NLS-1$ Log.log(Status.INFO, Log.TRAFO_CONNECTOR, "end2: " + connection.getEnds().get(1).getPartWithPort()); //$NON-NLS-1$ - ConnectorEnd end = ConnectorUtils.connEndForPart(connection, containedProperty); + ConnectorEnd end = ConnectorUtil.connEndForPart(connection, containedProperty); // other connector end targeted at containedProperty? if(end != null) { Port containedPort = (Port)end.getRole(); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java index dd8ad1f56a6..70f319beed4 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/BootLoaderGen.java @@ -25,7 +25,6 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.C_Cpp.Include; import org.eclipse.papyrus.FCM.InitPrecedence; import org.eclipse.papyrus.MARTE.MARTE_DesignModel.SRM.SW_Concurrency.SwSchedulableResource; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.StUtils; import org.eclipse.papyrus.qompass.designer.core.Utils; @@ -34,6 +33,7 @@ import org.eclipse.papyrus.qompass.designer.core.transformations.CompImplTrafos; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; import org.eclipse.papyrus.qompass.designer.core.transformations.PrefixConstants; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Connector; @@ -123,7 +123,7 @@ public class BootLoaderGen { */ Include cppInclude = StereotypeUtil.applyApp(m_bootLoader, Include.class); if (cppInclude == null) { - throw new TransformationException("Cannot apply cppInclude stereotype. Make sure that C/C++ profile is applied to your model"); + throw new TransformationException(Messages.BootLoaderGen_CannotApplyCppInclude); } String existingBody = cppInclude.getBody(); String bodyStr = @@ -278,7 +278,7 @@ public class BootLoaderGen { // check, if implementation contains a composite if (implementation.getOwnedOperation ("createConnections", null, null) != null) { boolean bCreateConn = false; for(Connector connector : implementation.getOwnedConnectors()) { - if(ConnectorUtils.isAssembly(connector)) { + if(ConnectorUtil.isAssembly(connector)) { bCreateConn = true; break; } @@ -355,7 +355,7 @@ public class BootLoaderGen { Class composite = part.getClass_(); for(Connector connector : composite.getOwnedConnectors()) { // must assure same connector end connects part & port - ConnectorEnd end = ConnectorUtils.connEndForPart(connector, part); + ConnectorEnd end = ConnectorUtil.connEndForPart(connector, part); if((end != null) && (end.getRole() == port)) { return true; } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepCreation.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepCreation.java index 5291a7a4118..ea21697bf52 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepCreation.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepCreation.java @@ -21,6 +21,7 @@ import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationRTException; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; +import org.eclipse.uml2.uml.AggregationKind; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Connector; @@ -184,8 +185,47 @@ public class DepCreation { } visitedClassifiers.push(typeOrImplem); - InstanceSpecification is = (InstanceSpecification) - cdp.createPackagedElement(name, UMLPackage.eINSTANCE.getInstanceSpecification()); + InstanceSpecification is; + // treat singleton + if(Utils.isSingleton((Class)typeOrImplem)) { + // is a singleton - exactly one instance exists + InstanceSpecification mainInstance = DepUtils.getMainInstance(cdp); + + // use canonical name for singleton instance - lower case for type-name + String partName = DeployConstants.singletonPrefix + typeOrImplem.getName().toLowerCase(); + name = mainInstance.getName() + DeployConstants.SEP_CHAR + partName; + PackageableElement pe = cdp.getPackagedElement(name); + + if(pe == null) { + // instance specification for singleton does not exist yet => create + + Classifier system = DepUtils.getClassifier(mainInstance); + Property singletonAttr = system.getAttribute(partName, typeOrImplem); + if((singletonAttr == null) && system instanceof Class) { + singletonAttr = ((Class) system).createOwnedAttribute(partName, typeOrImplem); + singletonAttr.setAggregation(AggregationKind.COMPOSITE_LITERAL); + } + + is = (InstanceSpecification) + cdp.createPackagedElement(name, UMLPackage.eINSTANCE.getInstanceSpecification()); + // create slot within main instance + createSlot(mainInstance, is, singletonAttr); + } + else if (pe instanceof InstanceSpecification) { + // exists already, return it without recursing into its sub-specifications + return (InstanceSpecification) pe; + } + else { + // unlikely case that a packaged element with the name + // <singletonISname> exists already, but is not an instance specification + throw new TransformationException(String.format( + Messages.DepCreation_SingletonExistsAlready, name)); + } + } + else { + is = (InstanceSpecification) + cdp.createPackagedElement(name, UMLPackage.eINSTANCE.getInstanceSpecification()); + } if(name.equals(DeployConstants.MAIN_INSTANCE)) { DepUtils.setMainInstance(cdp, is); @@ -255,7 +295,7 @@ public class DepCreation { if(((type instanceof Class) && Utils.isComponent((Class)type)) || type instanceof Node) { Class cl = (Class)type; - // hack: ad-hoc replication support. Better solution via design patterns + // TODO: ad-hoc replication support. Better solution via design patterns int upper = attribute.getUpper(); String infix = ""; //$NON-NLS-1$ @@ -267,8 +307,10 @@ public class DepCreation { } InstanceSpecification partIS = createDepPlan(cdp, cl, partName, createSlotsForConfigValues, visitedClassifiers); - - createSlot(is, partIS, attribute); + // may not create slot for singleton, since automatically done + if(!Utils.isSingleton((Class)type)) { + createSlot(is, partIS, attribute); + } } } else if(StereotypeUtil.isApplied(attribute, ConfigurationProperty.class) @@ -287,34 +329,10 @@ public class DepCreation { Messages.DepCreation_InfoCreateDepPlan, type.getQualifiedName())); if(Utils.isSingleton((Class)type)) { // is a singleton - exactly one instance exists - // use a common instance prefix for singletons - InstanceSpecification mainInstance = DepUtils.getMainInstance(cdp); - String partName = mainInstance.getName() + DeployConstants.SEP_CHAR + DeployConstants.singletonPrefix + attribute.getName(); - PackageableElement pe = cdp.getPackagedElement(partName); - - if(pe instanceof InstanceSpecification) { - // instance specification for singleton exists already - Slot slot = createSlot(is, (InstanceSpecification)pe, - attribute); - slot.setDefiningFeature(attribute); - } else if(type instanceof Class) { - // instance specification for singleton does not exist - // => create - // [case that a non-instance specification with the name - // <partName> exists already - // is not handled] - - Classifier system = DepUtils.getClassifier(mainInstance); - Property singletonAttr = null; - if (system instanceof Class) { - singletonAttr = ((Class) system).createOwnedAttribute(DeployConstants.singletonPrefix + attribute.getName(), type); - } - - InstanceSpecification singletonIS = createDepPlan(cdp, - (Class)type, partName, createSlotsForConfigValues, visitedClassifiers); - createSlot(is, singletonIS, attribute); - createSlot(mainInstance, singletonIS, singletonAttr); - } + // recursive call - pass empty name, since name for singletons is re-calculated. + InstanceSpecification singletonIS = createDepPlan(cdp, + (Class)type, "", createSlotsForConfigValues, visitedClassifiers); //$NON-NLS-1$ + createSlot(is, singletonIS, attribute); } } else if(type == null) { throw new TransformationException(String.format(Messages.DepCreation_TypeInAttributeUndefined, diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepUtils.java index 246945ce50f..6f04618aec7 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepUtils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/DepUtils.java @@ -348,6 +348,21 @@ public class DepUtils { } /** + * This method returns the instances contained within a composite instance + * specification for an assembly. Unlike @see getContainedInstances, this method only + * returns contained instances that are not shared. + */ + public static EList<InstanceSpecification> getContainedNonSharedInstances(InstanceSpecification is) { + EList<InstanceSpecification> contained = new BasicEList<InstanceSpecification>(); + for(Slot slot : is.getSlots()) { + InstanceSpecification instance = getInstance(slot); + if((instance != null) && !DepUtils.isShared(slot)) { + contained.add(instance); + } + } + return contained; + } + /** * return all slots that reference an instance specification * * @param is diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/Deploy.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/Deploy.java index c5cd6f75a70..29c9fd2685e 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/Deploy.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/Deploy.java @@ -48,29 +48,45 @@ public class Deploy { * @param instance * @throws TransformationException */ - public static Deploy distributeToNode(Copy copy, ILangSupport langSupport, InstanceSpecification node, - int nodeIndex, int numberOfNodes, InstanceSpecification instance) + public Deploy(Copy copy, ILangSupport langSupport, InstanceSpecification node, + int nodeIndex, int numberOfNodes) throws TransformationException { - Deploy deploy = new Deploy(); - deploy.bootLoaderGen = new BootLoaderGen(copy, nodeIndex, numberOfNodes); - deploy.node = node; + bootLoaderGen = new BootLoaderGen(copy, nodeIndex, numberOfNodes); + this.node = node; // change to flat copy eventually later (not yet working) - deploy.depInstance = new PartialCopy(); + depInstance = new PartialCopy(); - deploy.depInstance.init(copy, deploy.bootLoaderGen, node); + depInstance.init(copy, bootLoaderGen, node); // set a copy listener in order to assure that indirectly added classes // are taken into account as well + this.copy = copy; copy.preCopyListeners.add(new GatherConfigData(langSupport)); - // TODO: not nice at all (make non-static?) + } + + + /** + * distribute an instance, its contained sub-instances and the referenced + * classifiers to a certain node + * + * @param copy + * @param node + * @param nodeIndex + * @param numberOfNodes + * @param instance + * @throws TransformationException + */ + public InstanceSpecification distributeToNode(InstanceSpecification instance) + throws TransformationException + { Stack<Slot> slotPath = new Stack<Slot>(); - deploy.distributeToNode(false, slotPath, instance); + InstanceSpecification newRootIS = distributeToNode(false, slotPath, instance); - deploy.bootLoaderGen.addCreateConnections(); - deploy.bootLoaderGen.addInit(); - return deploy; + bootLoaderGen.addCreateConnections(); + bootLoaderGen.addInit(); + return newRootIS; } /** @@ -106,26 +122,34 @@ public class Deploy { InstanceSpecification containedInstance = DepUtils.getInstance(slot); if(containedInstance != null) { - StructuralFeature sf = slot.getDefiningFeature(); - boolean viaAllocAll = allocAll; - if (allocAll && (sf instanceof Property)) { - // only take allocation of parent instance into account, if composition - // However, problematic, since code gets copied anyway. - // viaAllocAll = (((Property) sf).getAggregation() == AggregationKind.COMPOSITE_LITERAL); + if (!DepUtils.isShared(slot)) { + StructuralFeature sf = slot.getDefiningFeature(); + boolean viaAllocAll = allocAll; + if (allocAll && (sf instanceof Property)) { + // only take allocation of parent instance into account, if composition + // However, problematic, since code gets copied anyway. + // viaAllocAll = (((Property) sf).getAggregation() == AggregationKind.COMPOSITE_LITERAL); + } + if(viaAllocAll || AllocUtils.getAllNodes(containedInstance).contains(node)) { + slotPath.push(slot); + if (sf instanceof Property) { + // place configurator before recursive call. Otherwise + // values put here would be ignored. + // TODO: instances are not copied to node model. Thus, the instances here are the same as in the + // configuration on the intermediate model. + // TODO: MIX of bootloaderGeneration and splitting. + InstanceConfigurator.configureInstance(containedInstance, (Property) sf, tmInstance); + } + // distribute subInstance + distributeToNode(allocAll, slotPath, containedInstance); + slotPath.pop(); + } } - if(viaAllocAll || AllocUtils.getAllNodes(containedInstance).contains(node)) { - // if(!containedInstance.getName().startsWith(singletonPrefix)) { + else if(allocAll || AllocUtils.getAllNodes(containedInstance).contains(node)) { slotPath.push(slot); - if (sf instanceof Property) { - // place configurator before recursive call. Otherwise - // values put here would be ignored. - // TODO: instances are not copied to node model. Thus, the instances here are the same as in the - // configuration on the intermediate model. - // TODO: MIX of bootloaderGeneration and splitting. - InstanceConfigurator.configureInstance(containedInstance, (Property) sf, tmInstance); - } - InstanceSpecification tmSubInstance = distributeToNode(allocAll, slotPath, containedInstance); - slotPath.pop(); + // bootLoaderGen.instanceConfig(slotPath, instance); + bootLoaderGen.addInstance(slotPath, containedInstance, null, node); + slotPath.pop(); } } else { // slot contains configuration of primitive attribute (no @@ -156,4 +180,6 @@ public class Deploy { protected InstanceSpecification node; protected InstanceDeployer depInstance; + + protected Copy copy; } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/PartialCopy.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/PartialCopy.java index cd509bd37f4..a49c7627a27 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/PartialCopy.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/deployment/PartialCopy.java @@ -16,9 +16,9 @@ package org.eclipse.papyrus.qompass.designer.core.deployment; import java.util.Stack; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Connector; @@ -72,9 +72,7 @@ public class PartialCopy implements InstanceDeployer { for (Slot slot : is.getSlots()) { copyPart(smCl, slot); } - // since we copied some of its attributes, the copy class created a shallow copy of the class itself - Class tmCl = (Class) copy.get(smCl); - + // since we copied some of its attributes, the copy class created a shallow copy of the class itself InstanceSpecification tmIS = (InstanceSpecification) copy.get(is); return tmIS; } @@ -106,8 +104,8 @@ public class PartialCopy implements InstanceDeployer { for(Connector smConnector : smCl.getOwnedConnectors()) { // check whether the newly added property enables the addition of connectors // that connect this port. - if(ConnectorUtils.connectsPart(smConnector, smPart)) { - ConnectorEnd otherEnd = ConnectorUtils.connEndNotPart(smConnector, smPart); + if(ConnectorUtil.connectsPart(smConnector, smPart)) { + ConnectorEnd otherEnd = ConnectorUtil.connEndNotPart(smConnector, smPart); // check whether the part references by the other end (i.e. that not connected with the part) // TODO: take connections without port into account Property otherPart = otherEnd.getPartWithPort(); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/BindingHelperExt.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/BindingHelperExt.java index bbde28a4b23..c8e363d11a9 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/BindingHelperExt.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/BindingHelperExt.java @@ -20,6 +20,7 @@ import org.eclipse.papyrus.FCM.BindingHelper; import org.eclipse.papyrus.FCM.util.IBindingHelper; import org.eclipse.papyrus.qompass.designer.core.listeners.CopyListener; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; +import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationRTException; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.TemplateBinding; @@ -73,6 +74,7 @@ public class BindingHelperExt { exception.printStackTrace(); } } - return null; + throw new TransformationRTException( + String.format("Cannot find binding helper <%s>", helperName)); } } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/IInstanceConfigurator.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/IInstanceConfigurator.java index 94df33a7003..3335a7b25cb 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/IInstanceConfigurator.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/IInstanceConfigurator.java @@ -32,5 +32,5 @@ public interface IInstanceConfigurator { * additional information, if the element that should be configured is part of a container, e.g. an interceptor * or an extension within the container. */ - public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstnace); + public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstance); } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/InstanceConfigurator.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/InstanceConfigurator.java index acb0084e888..f932174ccc2 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/InstanceConfigurator.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/extensions/InstanceConfigurator.java @@ -18,6 +18,7 @@ import org.eclipse.core.runtime.Platform; import org.eclipse.papyrus.FCM.ContainerRule; import org.eclipse.papyrus.FCM.UseInstanceConfigurator; import org.eclipse.papyrus.qompass.designer.core.Activator; +import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.InstanceSpecification; @@ -100,6 +101,10 @@ public class InstanceConfigurator { for(IConfigurationElement configElement : configElements) { try { final String iConfiguratorIDext = configElement.getAttribute("configuratorID"); //$NON-NLS-1$ + if(iConfiguratorIDext == null) { + throw new RuntimeException(String.format( + Messages.InstanceConfigurator_InvalidPluginExtension, iConfiguratorID)); + } if(iConfiguratorIDext.equals(iConfiguratorID)) { // TODO: cache returned instance (avoid creating a new instance each time => more efficient, no need for static attributes) final Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/messages.properties b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/messages.properties index c237acc8ada..a45464184ef 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/messages.properties +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/messages.properties @@ -1,8 +1,10 @@ BootLoaderGen_AtLeastOneBlockingCall=There must be at most one blocking "run" operation per node. Not adding "run" call for component instance %s. Existing invocations: %s +BootLoaderGen_CannotApplyCppInclude=Cannot apply cppInclude stereotype. Make sure that C/C++ profile is applied to your model BootLoaderGen_CannotRetrieveTemplate=Cannot retrieve bootLoader template (should be in %s) CommandSupport_NoEditingDomain=Can not get editing domain CommandSupport_ErrorDuringCmdExec=Error during command execution ConfigUtils_RuleWithoutBaseClass=A container rule has no base class (broken model library?) +DepCreation_SingletonExistsAlready=singleton instantiation: element with name %s exists already in deployment plan, but is not an instance specification DepCreation_CannotFindImplementation=cannot find suitable implementation for instance <%s> (given type <%s>) DepCreation_CircularReference=Class %s is referenced in a circle\! Thus, an infinite number of instance specifications would be required.\nrecursion path: DepCreation_DefiningFeatureNull=The defining feature of a slot of instance %s is null @@ -54,6 +56,8 @@ CompTypeTrafos_CannotFindType=Can not find type <%s>. Thus, unable to create sui ContainerTrafo_CannotApplyRule=Cannot apply container rule <%s>, since the type of one of its parts is undefined. Check for unresolved proxies in imports ContainerTrafo_CannotFindDelegationConn=(during interceptor transformation for container): cannot find existing delegation connector ContainerTrafo_InterceptionRuleButNoInterceptor=The part %s in rule %s has an interceptionRule, but is not typed with an interaction component +ContainerTrafo_RecursiveLWnotSupported=Recursive lightweight container rules currently not supported +InstanceConfigurator_InvalidPluginExtension=InstanceConfigurator: plugin extension for id %s is invalid InstantiateDepPlan_AcceleoErrors=Acceleo errors occured InstantiateDepPlan_AcceleoErrorsCheckLog=Acceleo errors occured during code generation. Please check the error log InstantiateDepPlan_CannotGenModel=Cannot generate model diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/sync/CompImplSync.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/sync/CompImplSync.java index 7ca8f25f993..12e185c3dee 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/sync/CompImplSync.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/sync/CompImplSync.java @@ -22,7 +22,6 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.papyrus.FCM.DerivedElement; import org.eclipse.papyrus.qompass.designer.core.CommandSupport; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Log; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.OperationUtils; @@ -31,6 +30,7 @@ import org.eclipse.papyrus.qompass.designer.core.PortUtils; import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.transformations.PrefixConstants; import org.eclipse.papyrus.qompass.designer.core.transformations.UpdateUtils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.BehavioralFeature; import org.eclipse.uml2.uml.Class; @@ -249,7 +249,7 @@ public class CompImplSync { if (implementation.getOwnedOperation(opName, null, null) != null) { continue; } - ConnectorEnd connEnd = ConnectorUtils.getDelegation(implementation, portInfo.getPort()); + ConnectorEnd connEnd = ConnectorUtil.getDelegation(implementation, portInfo.getPort()); // check that there is no delegation to a part which in turn has to implement the operations. if((providedIntf != null) && (connEnd == null)) { if(providedIntfs.contains(providedIntf)) { diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/BindingUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/BindingUtils.java index 67aedf7fa24..27293a7923a 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/BindingUtils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/BindingUtils.java @@ -37,7 +37,14 @@ import org.eclipse.uml2.uml.util.UMLUtil; public class BindingUtils { - public static Operation instantiateOperation(Copy copy, Element actual, Operation operation, Class boundClass) { + /** + * Bind an operation by copying the signature from the actual. + * @param copy the copier + * @param actual the actual. If an operation, its signature is copied to the template + * @param operation The operation template + * @return + */ + public static Operation instantiateOperation(Copy copy, Element actual, Operation operation) { try { Operation newOperation = copy.getCopy(operation); if(actual instanceof Operation) { diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/ConnectorBinding.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/ConnectorBinding.java index 888cb0d89da..9e1fceb0f57 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/ConnectorBinding.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/ConnectorBinding.java @@ -19,13 +19,13 @@ import java.util.Iterator; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.CreationUtils; import org.eclipse.papyrus.qompass.designer.core.Log; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.PortUtils; 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.ConnectorUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.ConnectableElement; @@ -129,9 +129,9 @@ public class ConnectorBinding { Messages.ConnectorBinding_InfoMatchOtherEnd, port.getName())); for(Connector connector : partConnector.getClass_().getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, partConnector)) { + if(ConnectorUtil.connectsPart(connector, partConnector)) { // the connector end targets a port of a part or the composite (in case of delegation) - ConnectorEnd connEnd = ConnectorUtils.connEndNotPart(connector, partConnector); + ConnectorEnd connEnd = ConnectorUtil.connEndNotPart(connector, partConnector); ConnectableElement connElem = connEnd.getRole(); if(connElem instanceof Port) { Port otherPort = (Port)connElem; @@ -229,9 +229,9 @@ public class ConnectorBinding { Property partConnector = (Property)partOrConnector; // iterate over the connectors of the composite containing the part for(Connector connector : partConnector.getClass_().getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, partConnector)) { + if(ConnectorUtil.connectsPart(connector, partConnector)) { // the connector end targets a port of a part or the composite (in case of delegation) - ConnectorEnd connEnd = ConnectorUtils.connEndNotPart(connector, partConnector); + ConnectorEnd connEnd = ConnectorUtil.connEndNotPart(connector, partConnector); actual = matchViaEnd(connEnd, port, partOrConnector, actual); if(actual != null) { found = true; diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiationListener.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiationListener.java index 2023871a381..9e3c5958ab4 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiationListener.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiationListener.java @@ -43,18 +43,11 @@ public class TemplateInstantiationListener implements CopyListener { } public void init(Copy copy, TemplateBinding binding, Object[] args) { - treatTemplate = false; - this.copy = copy; this.binding = binding; - this.args = args; } private TemplateBinding binding; - private Copy copy; - - private Object[] args; - private boolean treatTemplate; private static TemplateInstantiationListener templateInstantiationListener; @@ -70,138 +63,31 @@ public class TemplateInstantiationListener implements CopyListener { } protected EObject checkEObject(Copy copy, EObject sourceEObj) { - // try { - if(sourceEObj instanceof Element) { - if(sourceEObj instanceof OpaqueBehavior) { - OpaqueBehavior behavior = (OpaqueBehavior)sourceEObj; - // in case of a behavior, examine stereotype on associated operation - BehavioralFeature bf = behavior.getSpecification(); - if(bf != null) { - Template template = UMLUtil.getStereotypeApplication(bf, Template.class); - if(template != null) { - return null; - } + + // Specific treatment of OpaqueBehaviors: Template instantiations are typically managed + // by the associated operation which instantiates operation and behavior. In this case, the + // behavior should not be instantiated. + if(sourceEObj instanceof OpaqueBehavior) { + OpaqueBehavior behavior = (OpaqueBehavior)sourceEObj; + BehavioralFeature bf = behavior.getSpecification(); + if(bf != null) { + Template template = UMLUtil.getStereotypeApplication(bf, Template.class); + if(template != null) { + return null; } } - else { - Template template = UMLUtil.getStereotypeApplication((Element)sourceEObj, Template.class); - if((template != null)) { // && (!treatTemplateElement.containsKey(sourceEObj))) { - // treatTemplateElement.put(sourceEObj, true); - BindingHelper helper = template.getHelper(); - if (helper != null) { - return BindingHelperExt.applyHelper(helper, copy, binding, sourceEObj); - } - return sourceEObj; - - /* - if(sourceEObj instanceof Operation) { - Operation operation = (Operation)sourceEObj; - - Classifier actual = getFirstActualFromBinding(binding, operation); - Class boundClass = copy.getCopy(operation.getClass_()); - if(template.getKind() == TemplateKind.LOOP_OPERATIONS) { - // in case of loop operations, the template parameter is iteratively an - // operation of the actual (which should be an interface) in this case. - // - // The template operation typically inherits all parameters. This is expressed by - // a single parameter with the LOOP_PARAMETERS options (<%name%> as name, what as type?) - // cleaner (more general: if user writes loop with Acceleo as well?] - // // owns template operation parameter?? - Type passedActual = getPassedActual(template, actual, boundClass); - if(!(passedActual instanceof Interface)) { - return sourceEObj; - } - Interface passedActualIntf = (Interface)passedActual; - 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 = instantiateOperation(intfOperation, template, operation, boundClass); - removalList.add(operation); - for(Behavior method : operation.getMethods()) { - if(method instanceof OpaqueBehavior) { - Behavior newBehavior = - instantiateBehavior(intfOperation, template, (OpaqueBehavior)method); - newBehavior.setSpecification(last); - // 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 { - 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) { - if(template.getKind() == TemplateKind.LOOP_OPERATIONS) { - EnumerationLiteral literal = (EnumerationLiteral)sourceEObj; - Classifier actual = getFirstActualFromBinding(binding, literal); - // 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); - String newName = AcceleoDriverWrapper.evaluate(literal.getName(), intfOperation, args); - newLiteral.setName(newName); - } - return newLiteral; - } - } - */ + } + + if(sourceEObj instanceof Element) { + + Template template = UMLUtil.getStereotypeApplication((Element)sourceEObj, Template.class); + if((template != null)) { + BindingHelper helper = template.getHelper(); + if (helper != null) { + return BindingHelperExt.applyHelper(helper, copy, binding, sourceEObj); } } } return sourceEObj; - - /* - } catch (TransformationException e) { - // throw runtime exception - throw new RuntimeException(String.format(Messages.TemplateInstantiationListener_TrafoException, e.getMessage())); - } - */ - } - - - /* - private Type getPassedActual(Template template, Type actual, Class boundClass) { - if(template.getActualChoice() == ActualChoice.INTERFACE_OF_PPORT) { - return getInterfaceFromPortTypedWithActual(actual, boundClass, true); - } else if(template.getActualChoice() == ActualChoice.INTERFACE_OF_RPORT) { - // TODO: typically does not make sense to loop over it. - return getInterfaceFromPortTypedWithActual(actual, boundClass, false); - } else if(template.getActualChoice() == ActualChoice.PASS_ACTUAL) { - return actual; - } else { - // default behavior (common use in connectors): in case of a loop over operations, return actual - // from provided port - // TODO: Again, this is a hack! - if(template.getKind() == TemplateKind.LOOP_OPERATIONS) { - return getInterfaceFromPortTypedWithActual(actual, boundClass, true); - } else { - return actual; - } - } } - */ } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateUtils.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateUtils.java index 46e9e609071..ef8ea120182 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateUtils.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateUtils.java @@ -22,15 +22,25 @@ import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.qompass.designer.core.CreationUtils; import org.eclipse.papyrus.qompass.designer.core.Log; import org.eclipse.papyrus.qompass.designer.core.Messages; +import org.eclipse.papyrus.qompass.designer.core.PortUtils; +import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.ConnectableElement; +import org.eclipse.uml2.uml.Connector; +import org.eclipse.uml2.uml.ConnectorEnd; import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.EncapsulatedClassifier; import org.eclipse.uml2.uml.NamedElement; import org.eclipse.uml2.uml.Namespace; import org.eclipse.uml2.uml.Package; import org.eclipse.uml2.uml.PackageMerge; import org.eclipse.uml2.uml.ParameterableElement; +import org.eclipse.uml2.uml.Port; +import org.eclipse.uml2.uml.Property; +import org.eclipse.uml2.uml.StructuredClassifier; import org.eclipse.uml2.uml.TemplateBinding; import org.eclipse.uml2.uml.TemplateParameter; import org.eclipse.uml2.uml.TemplateParameterSubstitution; @@ -320,4 +330,62 @@ public class TemplateUtils { } return null; } + + /** + * Re-target connectors after a part has changed its type from template to an instantiation + * of this template. In this case, the roles of the connector ends still reference the port + * of the template instead of the bound template binding. + * The new roles are assigned based on an equal name, assuming that template instantiation + * does not change the name of the ports. + * + * @param composite a composite containing connectors + * @param part a part within the composite whose type has changed. + */ + public static void retargetConnectors(StructuredClassifier composite, Property part) { + Type partType = part.getType(); + if (partType instanceof EncapsulatedClassifier) { + EncapsulatedClassifier partTypeEC = (EncapsulatedClassifier) partType; + for(Connector connector : composite.getOwnedConnectors()) { + if(ConnectorUtil.connectsPart(connector, part)) { + // the connector end targets a port of a part or the composite (in case of delegation) + ConnectorEnd connEnd = ConnectorUtil.connEndForPart(connector, part); + // redirect role, if pointing to port + if(connEnd.getRole() instanceof Port) { + Port connectedTemplatePort = (Port)connEnd.getRole(); + Port connectedBoundPort = (Port)Utils.getNamedElementFromList( + PortUtils.getAllPorts(partTypeEC), connectedTemplatePort.getName()); + connEnd.setRole(connectedBoundPort); + } + } + } + } + } + + /** + * Re-target connectors after an unknown number of parts have changed their type from template + * to an instantiation of this template. In this case, the roles of the connector ends still + * reference the port of the template instead of the bound template binding. + * The new roles are assigned based on an equal name, assuming that template instantiation + * does not change the name of the ports. + * + * @param composite a composite containing connectors + */ + public static void retargetConnectors(StructuredClassifier composite) { + for(Connector connector : composite.getOwnedConnectors()) { + // the connector end targets a port of a part or the composite (in case of delegation) + for (ConnectorEnd connEnd : connector.getEnds()) { + Property part = connEnd.getPartWithPort(); + if ((part != null) && (part.getType() instanceof EncapsulatedClassifier)) { + EncapsulatedClassifier partTypeEC = (EncapsulatedClassifier) part.getType(); + ConnectableElement role = connEnd.getRole(); + EList<Port> ports = PortUtils.getAllPorts(partTypeEC); + if ((role instanceof Port) && !ports.contains(role)) { + // role is not in list of ports + Port connectedBoundPort = (Port)Utils.getNamedElementFromList(ports, role.getName()); + connEnd.setRole(connectedBoundPort); + } + } + } + } + } } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AbstractContainerTrafo.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AbstractContainerTrafo.java index 12ca2ec6579..eb6e8fee831 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AbstractContainerTrafo.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AbstractContainerTrafo.java @@ -95,13 +95,6 @@ public abstract class AbstractContainerTrafo { public void finalize() { } - - /** - * The created container implementation (prefixed with sm, since part of - * source model) - */ - protected Class smClass; - /** * The created container implementation (prefixed with tm, since part of * target model) diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AllocTransfo.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AllocTransfo.java index e68cb8e2e54..95f6cfbf170 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AllocTransfo.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/AllocTransfo.java @@ -3,9 +3,9 @@ package org.eclipse.papyrus.qompass.designer.core.transformations; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EStructuralFeature.Setting; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.deployment.AllocUtils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Connector; import org.eclipse.uml2.uml.ConnectorEnd; @@ -46,7 +46,7 @@ public class AllocTransfo { // TODO: currently, no support for setting up the priority of the main thread. // we need to get a cleaner solution for the main thread. // destroy eventual connector and associated thread => thread as component with unconnected start thread - Connector conn = ConnectorUtils.getConnector(composite, attribute, thread); + Connector conn = ConnectorUtil.getConnector(composite, attribute, thread); // Connector targetConn = copy.getCopy(conn); // Property targetThread = copy.getCopy(thread); if (conn != null) { @@ -62,7 +62,7 @@ public class AllocTransfo { thread.destroy(); } // check, if there is already a connector between the attribute and the thread - else if (!ConnectorUtils.existsConnector(composite, attribute, thread)) { + else if (!ConnectorUtil.existsConnector(composite, attribute, thread)) { // no connector => create; Class component = (Class) type; Connector c = composite.createOwnedConnector("alloc to " + thread.getName()); //$NON-NLS-1$ diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/CompImplTrafos.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/CompImplTrafos.java index f87ce91d5a5..da51cfadac2 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/CompImplTrafos.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/CompImplTrafos.java @@ -22,11 +22,11 @@ import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.C_Cpp.Ptr; import org.eclipse.papyrus.FCM.PortKind; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.PortInfo; import org.eclipse.papyrus.qompass.designer.core.PortUtils; import org.eclipse.papyrus.qompass.designer.core.Utils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; import org.eclipse.uml2.uml.AggregationKind; import org.eclipse.uml2.uml.Association; @@ -124,7 +124,7 @@ public class CompImplTrafos { UMLPackage.eINSTANCE.getOpaqueBehavior()); op.getMethods().add(behavior); - ConnectorEnd ce = ConnectorUtils.getDelegation(implementation, portInfo.getModelPort()); + ConnectorEnd ce = ConnectorUtil.getDelegation(implementation, portInfo.getModelPort()); // if there is an delegation to an inner property, delegate to it // Make distinction between delegation to component (with a port) or // "normal" class (without). @@ -159,7 +159,7 @@ public class CompImplTrafos { Interface providedIntfInCopy = (Interface) copy.get(providedIntf); implementsIntf = implementation.getInterfaceRealization(null, providedIntfInCopy) != null; } - if (implementsIntf || true) { + if (implementsIntf) { body = "return this;"; //$NON-NLS-1$ } else { @@ -243,7 +243,7 @@ public class CompImplTrafos { UMLPackage.eINSTANCE.getOpaqueBehavior()); op.getMethods().add(behavior); - ConnectorEnd ce = ConnectorUtils.getDelegation(implementation, portInfo.getModelPort()); + ConnectorEnd ce = ConnectorUtil.getDelegation(implementation, portInfo.getModelPort()); // if there is an delegation to an inner property, delegate to it // Make distinction between delegation to component (with a port) or // "normal" class (without). @@ -253,7 +253,10 @@ public class CompImplTrafos { body = part.getName(); ConnectableElement role = ce.getRole(); if(role instanceof Port) { - body += refOp(part) + opName; + // in case of a delegation, use name of target port which might be different + String targetOpName = PrefixConstants.connectQ_Prefix + role.getName(); + body += refOp(part) + targetOpName; + // TODO: no check that multiplicity of both port matches if((portInfo.getUpper() > 1) || (portInfo.getUpper() == -1)) { body += "(index, ref);"; //$NON-NLS-1$ } else { @@ -322,7 +325,7 @@ public class CompImplTrafos { Map<ConnectorEnd, Integer> indexMap = new HashMap<ConnectorEnd, Integer>(); for(Connector connector : implementation.getOwnedConnectors()) { - if(ConnectorUtils.isAssembly(connector)) { + if(ConnectorUtil.isAssembly(connector)) { // Boolean associationBased = false; if (connector.getEnds().size() != 2) { throw new TransformationException("Connector <" + connector.getName() + "> does not have two ends. This is currently not supported"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -502,8 +505,8 @@ public class CompImplTrafos { * @return */ public static boolean instantiateViaBootloader(Class implementation) { - return Utils.isCompType(implementation) || - implementation.isAbstract() || Utils.isSingleton(implementation) || + return + implementation.isAbstract() || Utils.isAssembly(implementation); } @@ -539,7 +542,7 @@ public class CompImplTrafos { * @return */ protected static String refOp(Property part) { - return instantiateViaBootloader(part) ? + return ((part.getAggregation() == AggregationKind.SHARED_LITERAL) || StereotypeUtil.isApplied(part, Ptr.class)) ? "->" : "."; //$NON-NLS-1$ //$NON-NLS-2$ } } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ConnectorReification.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ConnectorReification.java index 8c385174d53..3b46d557aa9 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ConnectorReification.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ConnectorReification.java @@ -27,16 +27,15 @@ import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.FCM.InteractionComponent; import org.eclipse.papyrus.infra.core.Activator; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.Log; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.PortUtils; -import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.deployment.AllocUtils; import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; import org.eclipse.papyrus.qompass.designer.core.templates.ConnectorBinding; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateInstantiation; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.ConnectableElement; import org.eclipse.uml2.uml.Connector; @@ -153,21 +152,8 @@ public class ConnectorReification { } Property tmConnectorPart = copy.getCopy(smConnectorPart); tmConnectorPart.setType(connectorImplem); - // now retarget connectors towards this part - - for(Connector connector : tmComponent.getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, tmConnectorPart)) { - // the connector end targets a port of a part or the composite (in case of delegation) - ConnectorEnd connEnd = ConnectorUtils.connEndForPart(connector, tmConnectorPart); - // redirect role, if pointing to port - if(connEnd.getRole() instanceof Port) { - Port connectedTemplatePort = (Port)connEnd.getRole(); - Port connectedBoundPort = (Port)Utils.getNamedElementFromList( - PortUtils.getAllPorts(connectorImplem), connectedTemplatePort.getName()); - connEnd.setRole(connectedBoundPort); - } - } - } + // now re-target connectors towards this part + TemplateUtils.retargetConnectors(tmComponent, tmConnectorPart); return tmConnectorPart; } @@ -356,7 +342,7 @@ public class ConnectorReification { // reified connector EList<Connector> connSubset = new BasicEList<Connector>(); for(Connector connector : composite.getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, reifiedConnector)) { + if(ConnectorUtil.connectsPart(connector, reifiedConnector)) { connSubset.add(connector); } } @@ -368,7 +354,7 @@ public class ConnectorReification { // check whether a port of the reified connector is not yet // connected. for(Connector connector : connSubset) { - if(ConnectorUtils.connectsPort(connector, port)) { + if(ConnectorUtil.connectsPort(connector, port)) { connected = true; } } @@ -379,7 +365,7 @@ public class ConnectorReification { // the port is connected, i.e. we do not want to connect the port to // potentially set of ports (todo: restriction always useful?) for(Connector connector : connSubset) { - ConnectorEnd connEnd = ConnectorUtils.connEndNotPart( + ConnectorEnd connEnd = ConnectorUtil.connEndNotPart( connector, reifiedConnector); Property otherPart = connEnd.getPartWithPort(); // this is a part which is connected with the reified @@ -448,12 +434,12 @@ public class ConnectorReification { // loop over connectors of composite that originate from passed part. for(Connector connector : composite.getOwnedConnectors()) { - ConnectorEnd myEnd = ConnectorUtils.connEndForPart(connector, part); + ConnectorEnd myEnd = ConnectorUtil.connEndForPart(connector, part); if(myEnd == null) { // the connector does not connect this part continue; } - ConnectorEnd otherEnd = ConnectorUtils.connEndNotPart(connector, + ConnectorEnd otherEnd = ConnectorUtil.connEndNotPart(connector, part); Property otherPart = otherEnd.getPartWithPort(); @@ -465,9 +451,7 @@ public class ConnectorReification { for(Slot slot : compositeIS.getSlots()) { if(slot.getDefiningFeature() == otherPart) { InstanceSpecification containedInstance = DepUtils.getInstance(slot); - // TODO: too complicated, if the non-connector is a composite as well, it must be clearly allocated - EList<InstanceSpecification> nodes = AllocUtils.getAllNodesForPort( - containedInstance, otherPort); + EList<InstanceSpecification> nodes = AllocUtils.getAllNodesForPort(containedInstance, otherPort); AllocUtils.propagateNodesViaPort( DepUtils.getInstance(partSlot), myPort, nodes); break; diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java index 40d7e55ae02..20927702bed 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java @@ -21,11 +21,15 @@ import java.util.Map; 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.FCM.BindTemplate; import org.eclipse.papyrus.FCM.ContainerRule; +import org.eclipse.papyrus.FCM.ContainerRuleKind; import org.eclipse.papyrus.FCM.InteractionComponent; import org.eclipse.papyrus.FCM.InterceptionKind; import org.eclipse.papyrus.FCM.InterceptionRule; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; +import org.eclipse.papyrus.FCM.Singleton; +import org.eclipse.papyrus.FCM.util.FCMUtil; +import org.eclipse.papyrus.FCM.util.MapUtil; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.PortUtils; import org.eclipse.papyrus.qompass.designer.core.StUtils; @@ -33,9 +37,9 @@ import org.eclipse.papyrus.qompass.designer.core.Utils; import org.eclipse.papyrus.qompass.designer.core.acceleo.UMLTool; import org.eclipse.papyrus.qompass.designer.core.deployment.DepCreation; import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; -import org.eclipse.papyrus.qompass.designer.core.deployment.DeployConstants; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateInstantiation; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil; import org.eclipse.uml2.uml.Association; import org.eclipse.uml2.uml.Class; @@ -46,11 +50,11 @@ import org.eclipse.uml2.uml.EncapsulatedClassifier; import org.eclipse.uml2.uml.Feature; import org.eclipse.uml2.uml.InstanceSpecification; import org.eclipse.uml2.uml.Package; -import org.eclipse.uml2.uml.PackageableElement; import org.eclipse.uml2.uml.Port; import org.eclipse.uml2.uml.Property; import org.eclipse.uml2.uml.Slot; import org.eclipse.uml2.uml.TemplateBinding; +import org.eclipse.uml2.uml.TemplateParameter; import org.eclipse.uml2.uml.TemplateSignature; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.UMLPackage; @@ -98,17 +102,31 @@ public class ContainerTrafo extends AbstractContainerTrafo { */ @Override public void createContainer(Class smComponent, Class tmComponent) throws TransformationException { - Package tmPkgOwner = tmComponent.getNearestPackage(); - // create a container with the suitable postfix + Package tmPkgOwner; + if (tmComponent.eResource() == tmCDP.eResource()) { + // tmComponent is in same model as tmContainer + tmPkgOwner = tmComponent.getNearestPackage(); + } + else { + // tmComponent is not a member of the target model. This is the case, if tmComponent is + // in an imported model that has not been copied during the transformation towards an intermediate + // model. + tmPkgOwner = MapUtil.getAndCreate(Utils.getTop(tmCDP), tmComponent.allNamespaces(), true); + } + // create a container with the suitable postfix tmContainerImpl = tmPkgOwner.createOwnedClass(tmComponent.getName() + containerPostfix, false); + + // Apply singleton to container, if original class is a singleton + boolean isSingleton = StereotypeUtil.isApplied(smComponent, Singleton.class); + if (isSingleton) { + StereotypeUtil.apply(tmContainerImpl, Singleton.class); + } Copy.copyID(tmComponent, tmContainerImpl, containerPostfix); // add part and slot corresponding to component; executorPart = tmContainerImpl.createOwnedAttribute(executorPartName, tmComponent); Copy.copyID(tmComponent, executorPart, "e"); //$NON-NLS-1$ - this.smClass = smComponent; - executorPart.setIsComposite(true); // copy ports from the executor (tmComponent) to the container @@ -118,7 +136,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { for(Port port : PortUtils.getAllPorts(tmComponent)) { // copy port if (port.getVisibility() == VisibilityKind.PUBLIC_LITERAL) { - Port newPort = EcoreUtil.copy(port); // don't use E3CM copy, since this is not a copy from source to target model + Port newPort = EcoreUtil.copy(port); // don't use Qompass copy, since this is not a copy from source to target model tmContainerImpl.getOwnedAttributes().add(newPort); StUtils.copyStereotypes(port, newPort); @@ -190,26 +208,17 @@ public class ContainerTrafo extends AbstractContainerTrafo { // containers.put(tmComponent, this); EList<Slot> connectorSlots = new BasicEList<Slot>(); + executorIS = tmIS; // now create instances for the contained elements for(Property extensionPart : tmContainerImpl.getAttributes()) { Type tmContainerExtImpl = extensionPart.getType(); if(tmContainerExtImpl instanceof Class) { - if (DepUtils.getSlot(executorIS, extensionPart) == null) { + if (DepUtils.getSlot(containerIS, extensionPart) == null) { // no slot for part exists => assume that the part has been added by the container and create an instance specification for it. - String isName; InstanceSpecification containerExtIS = null; - if(Utils.isSingleton((Class)tmContainerExtImpl)) { - // is a singleton - exactly one instance exists - // use a common instance prefix for singletons - isName = DeployConstants.singletonPrefix + extensionPart.getName(); - PackageableElement pe = tmCDP.getPackagedElement(isName); - if (pe instanceof InstanceSpecification) { - containerExtIS = (InstanceSpecification) pe; - } - } - else { - isName = containerIS.getName() + "." + extensionPart.getName(); //$NON-NLS-1$ - } + + String isName = containerIS.getName() + "." + extensionPart.getName(); //$NON-NLS-1$ + // create sub-instance and slot for extensions if (containerExtIS == null) { containerExtIS = DepCreation.createDepPlan(tmCDP, (Class)tmContainerExtImpl, isName, false); @@ -304,23 +313,21 @@ public class ContainerTrafo extends AbstractContainerTrafo { // DepUtils.chooseImplementation((Class) type, // new BasicEList<InstanceSpecification>(), false); - if(StereotypeUtil.isApplied(extOrInterceptor, InteractionComponent.class)) { + if(StereotypeUtil.isApplied(part, InterceptionRule.class)) { + if(StereotypeUtil.isApplied(extOrInterceptor, InteractionComponent.class)) { - InterceptionRule interceptionRule = UMLUtil.getStereotypeApplication(part, InterceptionRule.class); - InterceptionKind interceptionKind = InterceptionKind.INTERCEPT_ALL; // default: intercept all ports - EList<Feature> interceptFeatures = null; - if(interceptionRule != null) { - interceptionKind = interceptionRule.getInterceptionKind(); - interceptFeatures = interceptionRule.getInterceptionSet(); - } - EList<Property> interceptorParts = + InterceptionRule interceptionRule = UMLUtil.getStereotypeApplication(part, InterceptionRule.class); + InterceptionKind interceptionKind = interceptionRule.getInterceptionKind(); + EList<Feature> interceptFeatures = interceptionRule.getInterceptionSet(); + EList<Property> interceptorParts = expandInterceptorExtension(interceptionKind, interceptFeatures, extOrInterceptor, tmComponent); - interceptorPartsMap.put(part, interceptorParts); - } - else if(StereotypeUtil.isApplied(part, InterceptionRule.class)) { - throw new TransformationException(String.format( - Messages.ContainerTrafo_InterceptionRuleButNoInterceptor, - part.getName(), smContainerRule.getBase_Class().getName())); + interceptorPartsMap.put(part, interceptorParts); + } + else { + throw new TransformationException(String.format( + Messages.ContainerTrafo_InterceptionRuleButNoInterceptor, + part.getName(), smContainerRule.getBase_Class().getName())); + } } else { Property extensionPart = @@ -333,7 +340,8 @@ public class ContainerTrafo extends AbstractContainerTrafo { } } createConnectorForAssociations(); - // tell copy that tmcontainerImpl is associated with the smContainerRule + + // tell copier that tmcontainerImpl is associated with the smContainerRule // register a package template (although it is not a template) to assure that the connectors // get copied, although they are in a different resource (only the connectors are copied, not // the types of the referenced parts). @@ -344,7 +352,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { for(Connector connector : smContainerRule.getBase_Class().getOwnedConnectors()) { Property ruleInterceptorPart = null; for(Property part : interceptorPartsMap.keySet()) { - if(ConnectorUtils.connectsPart(connector, part)) { + if(ConnectorUtil.connectsPart(connector, part)) { // this connector is a connection between an interceptor (and another part which may not // be an interceptor => TODO: validation rule yet to write // we need to copy this connector multiple times, once for each associated interceptor part @@ -375,6 +383,8 @@ public class ContainerTrafo extends AbstractContainerTrafo { } } copy.setPackageTemplate(null, null); + + TemplateUtils.retargetConnectors(tmContainerImpl); } /** @@ -392,15 +402,62 @@ public class ContainerTrafo extends AbstractContainerTrafo { if(signature == null) { // no template signature, just copy the container extension into the target model tmContainerExtImpl = copy.getCopy(smContainerExtImpl); - } else { - // template signature found, instantiate container extension via the - // template binding mechanism - TemplateBinding binding = TemplateUtils.fixedBinding(copy.target, smContainerExtImpl, tmComponent); + } + else { + // template signature found, instantiate container extension via template binding mechanism + Classifier actual; + if (StereotypeUtil.isApplied(smExtensionPart, BindTemplate.class)) { + BindTemplate bt = UMLUtil.getStereotypeApplication(smExtensionPart, BindTemplate.class); + // use explicit binding from stereotype + actual = (Classifier) bt.getActual().get(0); + } + else { + // use executor component as actual + actual = tmComponent; + } + // template signature and instantiate container extension via the + // template binding mechanism, use executor component as actual + TemplateBinding binding = TemplateUtils.fixedBinding(copy.target, smContainerExtImpl, actual); Object[] args = new Object[]{}; TemplateInstantiation ti = new TemplateInstantiation(copy, binding, args); tmContainerExtImpl = (Class)ti.bindNamedElement(smContainerExtImpl); } + // -------------------------------------------------- + // a container extension could be subject to container rules as well, i.e. need + // to handle recursive rule application. + EList<ContainerRule> rules = FCMUtil.getAllContainerRules(smContainerExtImpl); + + // get container trafo instance, if already existing + AbstractContainerTrafo containerTrafo = ContainerTrafo.get(tmContainerExtImpl); + + if(containerTrafo == null) { + // no container exists, check rules and create eventually + for(ContainerRule rule : rules) { + if(RuleManagement.isRuleActive(rule)) { + // at least one active rule => create container (or get previously instantiated)) + if(containerTrafo == null) { + if(rule.getKind() == ContainerRuleKind.LIGHT_WEIGHT_OO_RULE) { + throw new TransformationException(Messages.ContainerTrafo_RecursiveLWnotSupported); + } + else { + containerTrafo = new ContainerTrafo(copy, tmCDP, null); + } + containerTrafo.createContainer(smContainerExtImpl, tmContainerExtImpl); + } + else { + // configure only?? + } + containerTrafo.applyRule(rule, smContainerExtImpl, tmContainerExtImpl); + } + } + if (containerTrafo != null) { + containerTrafo.finalize(); + tmContainerExtImpl = ((ContainerTrafo) containerTrafo).getContainer(); + } + } + // -------------------------------------------------- + // add part associated with the extension to the container extensionPart = tmContainerImpl.createOwnedAttribute(name, tmContainerExtImpl); @@ -408,6 +465,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { extensionPart.setAggregation(smExtensionPart.getAggregation()); Copy.copyMultElemModifiers(smExtensionPart, extensionPart); Copy.copyFeatureModifiers(smExtensionPart, extensionPart); + return extensionPart; } @@ -436,13 +494,27 @@ public class ContainerTrafo extends AbstractContainerTrafo { if(extKind == InterceptionKind.INTERCEPT_ALL_IN) { // IN-PORT = provided port match = (PortUtils.getProvided(port) != null); - } else if(extKind == InterceptionKind.INTERCEPT_ALL_OUT) { + } + else if(extKind == InterceptionKind.INTERCEPT_ALL_OUT) { // IN-PORT = provided port match = (PortUtils.getRequired(port) != null); - } else if(extKind == InterceptionKind.INTERCEPT_SOME) { + } + else if(extKind == InterceptionKind.INTERCEPT_SOME) { // comparison based on name, since in different models match = (Utils.getNamedElementFromList(featureList, port.getName()) != null); } + else if(extKind == InterceptionKind.INTERCEPT_MATCHING) { + EList<Port> interceptorPorts = PortUtils.getAllPorts(smContainerConnImpl); + match = false; + // get first port from interception connector that is typed with a template parameter + for (Port interceptorPort : interceptorPorts) { + if (interceptorPort.getType().getOwner() instanceof TemplateParameter) { + match = (PortUtils.getKind(port) == PortUtils.getKind(interceptorPort)); + break; + } + } + } + // else INTERCEPT_ALL_PORT => match remains true if(!match) { // port does not match criterion, continue with next port @@ -454,7 +526,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { Connector interceptionConnector = null; // get delegation connector for(Connector connector : tmContainerImpl.getOwnedConnectors()) { - if(ConnectorUtils.connectsPort(connector, port)) { + if(ConnectorUtil.connectsPort(connector, port)) { interceptionConnector = connector; break; } @@ -465,7 +537,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { throw new TransformationException(Messages.ContainerTrafo_CannotFindDelegationConn); } - interceptionConnector.setName(interceptorName + port.getName() + counter); + interceptionConnector.setName(interceptionName); org.eclipse.papyrus.FCM.Connector fcmConn = StereotypeUtil.applyApp(interceptionConnector, org.eclipse.papyrus.FCM.Connector.class); InteractionComponent fcmConnType = UMLUtil.getStereotypeApplication(smContainerConnImpl, InteractionComponent.class); fcmConn.setIc(fcmConnType); @@ -529,11 +601,12 @@ public class ContainerTrafo extends AbstractContainerTrafo { /** * Create an connector for parts that have an association. The rationale - * behind this is + * behind this is support connections between the state machine in the container + * and the executor. * */ public void createConnectorForAssociations() { - // TODO: keep list of added parts, only recheck those! + // TODO: keep list of added parts, only re-check those! for(Property part : Utils.getParts(tmContainerImpl)) { if(part.getType() == null) { @@ -555,7 +628,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { // found an association between two parts of the // container => create connection, // unless already existing. - if(!ConnectorUtils.existsConnector(tmContainerImpl, part, checkPart)) { + if(!ConnectorUtil.existsConnector(tmContainerImpl, part, checkPart)) { Connector conn = tmContainerImpl.createOwnedConnector(part.getName() + "_" + checkPart.getName()); //$NON-NLS-1$ conn.setType(association); conn.createEnd().setRole(part); @@ -595,7 +668,8 @@ public class ContainerTrafo extends AbstractContainerTrafo { for (Port svcPort : containerSvc.getOwnedPorts()) { if (PortUtils.matches(executorPort, svcPort, true)) { // create connector - Connector c = tmContainerImpl.createOwnedConnector("auto"); //$NON-NLS-1$ + Connector c = tmContainerImpl.createOwnedConnector( + String.format("auto from %s to %s", executorPart.getName(), svcPart.getName())); //$NON-NLS-1$ ConnectorEnd ce1 = c.createEnd(); ConnectorEnd ce2 = c.createEnd(); ce1.setPartWithPort(executorPart); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/Copy.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/Copy.java index 790048a6f5d..b930350bf66 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/Copy.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/Copy.java @@ -308,8 +308,20 @@ public class Copy extends Copier { private Stack<Namespace> boundPackages; + /** + * Remove an element and its children from the map to enable subsequent copies, in particular if the + * same element (e.g. an operation) is bound multiple times within a template instantiation. + * TODO: there must be a better way to do this. + * @param element + */ public void removeForCopy(EObject element) { templateMap.remove(element); + if(element instanceof Element) { + // also remove applied stereotypes + for (EObject stereoApplication : ((Element) element).getStereotypeApplications()) { + removeForCopy(stereoApplication); + } + } EClass eClass = element.eClass(); for(int i = 0, size = eClass.getFeatureCount(); i < size; ++i) { diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/FlattenInteractionComponents.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/FlattenInteractionComponents.java index 20d0a82461a..92404288324 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/FlattenInteractionComponents.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/FlattenInteractionComponents.java @@ -20,9 +20,9 @@ import java.util.Map; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.FCM.InteractionComponent; -import org.eclipse.papyrus.qompass.designer.core.ConnectorUtils; import org.eclipse.papyrus.qompass.designer.core.deployment.DepPlanUtils; import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; +import org.eclipse.papyrus.uml.tools.utils.ConnectorUtil; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Connector; @@ -140,10 +140,10 @@ public class FlattenInteractionComponents { boolean foundConnector = false; // now redirect connectors: find whether a port delegates to the fragment for(Connector connector : composite.getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, fragmentPart)) { + if(ConnectorUtil.connectsPart(connector, fragmentPart)) { foundConnector = true; // internal connector for the part, check whether delegation - ConnectorEnd ce = ConnectorUtils.connEndNotPart(connector, fragmentPart); + ConnectorEnd ce = ConnectorUtil.connEndNotPart(connector, fragmentPart); if((ce != null) && (ce.getPartWithPort() == null)) { // delegation connector, need to re-targed connections to external port Port port = (Port)ce.getRole(); @@ -203,8 +203,8 @@ public class FlattenInteractionComponents { */ public void retargetConnections(Class containingComposite, Port port, Property part, Property subPart) { for(Connector connector : containingComposite.getOwnedConnectors()) { - if(ConnectorUtils.connectsPart(connector, part) && ConnectorUtils.connectsPort(connector, port)) { - ConnectorEnd ce = ConnectorUtils.connEndForPart(connector, part); + if(ConnectorUtil.connectsPart(connector, part) && ConnectorUtil.connectsPort(connector, port)) { + ConnectorEnd ce = ConnectorUtil.connEndForPart(connector, part); if(ce != null) { // TODO: only with with connections targeting a port of a part, not with // those targeting directly a part diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/InstantiateDepPlan.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/InstantiateDepPlan.java index ff8779bb0f0..a1e27391ee8 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/InstantiateDepPlan.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/InstantiateDepPlan.java @@ -199,17 +199,19 @@ public class InstantiateDepPlan { InstanceConfigurator.onNodeModel = false; MainModelTrafo mainModelTrafo = new MainModelTrafo(tmpCopy, tmCDP); InstanceSpecification newRootIS = mainModelTrafo.transformInstance(rootIS, null); - DeploymentPlan newCDP = StereotypeUtil.applyApp(tmCDP, DeploymentPlan.class); - newCDP.setMainInstance(newRootIS); monitor.worked(1); // 1c: late bindings // LateEval.bindLateOperations(); // 3: distribute to nodes + // UpdateDerivedInterfaces.updateIntfs(newRootIS); + ApplyInstanceConfigurators.applyInstanceConfigurators(newRootIS); FlattenInteractionComponents.getInstance().flattenAssembly(newRootIS, null); + + PropagateAllocationToSharedInstances.propagateAllocation(newRootIS); String tmpPath = tmpMM.getPath(project, TEMP_MODEL_FOLDER, tmpModel.getName() + TEMP_MODEL_POSTFIX); tmpMM.saveModel(tmpPath); @@ -263,7 +265,9 @@ public class InstantiateDepPlan { ILangSupport langSupport = LanguageSupport.getLangSupport(targetLanguage); langSupport.resetConfigurationData(); - Deploy deploy = Deploy.distributeToNode(targetCopy, langSupport, node, nodeIndex, nodes.size(), newRootIS); + Deploy deploy = new Deploy(targetCopy, langSupport, node, nodeIndex, nodes.size()); + InstanceSpecification nodeRootIS = deploy.distributeToNode(newRootIS); + UpdateDerivedInterfaces.updateIntfs(nodeRootIS); if(monitor.isCanceled()) { return; @@ -275,11 +279,14 @@ public class InstantiateDepPlan { // Due to the copying of imports, the top-level package has changed which implies that new // derived interfaces are put into a different package and the derivedInterfaces package in // the original root becomes obsolete. Delete this obsolete package, if existing. - NamedElement derivedInterfaces = Utils.getQualifiedElement(genModel, "root::derivedInterfaces"); //$NON-NLS-1$ - if(derivedInterfaces instanceof Package) { - derivedInterfaces.destroy(); + for (PackageableElement pe : genModel.getPackagedElements()) { + if (pe instanceof Package) { + NamedElement derivedInterfaces = ((Package) pe).getPackagedElement("derivedInterfaces"); //$NON-NLS-1$ + if(derivedInterfaces instanceof Package) { + derivedInterfaces.destroy(); + } + } } - // 2c: add get_p/connect_q operations // caveat: may modify imported classes CompImplTrafos.bootloader = deploy.getBootloader(); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/LWContainerTrafo.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/LWContainerTrafo.java index d47ec6d4196..75b169e87ab 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/LWContainerTrafo.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/LWContainerTrafo.java @@ -109,7 +109,6 @@ public class LWContainerTrafo extends AbstractContainerTrafo { // => clarify, how container handles super-classes, i.e. if it inherits ports as well (from a container of the abstract component) or not (not trivial at all!) // TODO: don't copy derived operations - this.smClass = smClass; this.tmClass = tmClass; // create a copy of all operations operations = new BasicEList<Operation>(smClass.getAllOperations()); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/MainModelTrafo.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/MainModelTrafo.java index 8bfea62d6af..79dee8f8763 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/MainModelTrafo.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/MainModelTrafo.java @@ -182,8 +182,19 @@ public class MainModelTrafo { } String instName = smIS.getName(); + // first check, if instance specification exists already. This may be the case for explicitly modeled singleton instances. InstanceSpecification tmIS = (InstanceSpecification) - tmCDP.createPackagedElement(instName, UMLPackage.eINSTANCE.getInstanceSpecification()); + tmCDP.getPackagedElement(instName); + if (tmIS == null) { + tmIS = (InstanceSpecification) + tmCDP.createPackagedElement(instName, UMLPackage.eINSTANCE.getInstanceSpecification()); + } + if (smDF == null) { + // no defining feature => must be main instance + // => apply deployment plan stereotype and set main instance + DeploymentPlan newCDP = StereotypeUtil.applyApp(tmCDP, DeploymentPlan.class); + newCDP.setMainInstance(tmIS); + } Class tmComponent = copy.getCopy(smComponent); if(tmComponent == null) { @@ -238,7 +249,13 @@ public class MainModelTrafo { // copy node allocation for(InstanceSpecification smNode : AllocUtils.getNodes(smIS)) { InstanceSpecification tmNode = copy.getCopy(smNode); - AllocUtils.allocate(tmIS, tmNode); + if (containerIS != null) { + // allocate container instead of executor. + AllocUtils.allocate(containerIS, tmNode); + } + else { + AllocUtils.allocate(tmIS, tmNode); + } if(!nodeHandled.containsKey(tmNode)) { // check if node (on an instance level) has already been treated. This is required, since many @@ -263,7 +280,6 @@ public class MainModelTrafo { // executor itself does not make much sense, additional operation "createHwContainer" // obtain property related to node instance - Slot smNodeSlot = DepUtils.getParentSlot(smNode); Package smCDP = smIS.getNearestPackage(); DeploymentPlan smFCM_CDP = UMLUtil.getStereotypeApplication(smCDP, DeploymentPlan.class); @@ -403,7 +419,9 @@ public class MainModelTrafo { // copy slots from the source deployment plan that are related to connector configuration InstanceSpecification smConnectorIS = DepUtils.getNamedSubInstance(smIS, smConnector.getName()); if(smConnectorIS != null) { - copy.put(smConnectorIS, tmReifiedConnectorIS); + // use putPair instead of put only - see bug 426748, avoid that classifier attribute points + // to two classifiers (bound and unbound) + copy.putPair(smConnectorIS, tmReifiedConnectorIS); for(Slot smSlot : smConnectorIS.getSlots()) { copy.getCopy(smSlot); } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/PropagateAllocationToSharedInstances.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/PropagateAllocationToSharedInstances.java new file mode 100644 index 00000000000..cc34e630d6e --- /dev/null +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/PropagateAllocationToSharedInstances.java @@ -0,0 +1,58 @@ +/***************************************************************************** + * 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.designer.core.transformations; + +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.UniqueEList; +import org.eclipse.papyrus.qompass.designer.core.Log; +import org.eclipse.papyrus.qompass.designer.core.deployment.AllocUtils; +import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; +import org.eclipse.uml2.uml.InstanceSpecification; +import org.eclipse.uml2.uml.Slot; + + +/** + * Propagate allocation to shared instances: if a class references another instance + * via sharing, the shared instance must be allocated on the node of the referencing + * class as well. + * + */ +public class PropagateAllocationToSharedInstances { + public static void propagateAllocation(InstanceSpecification instance) { + propagateAllocation(instance, new UniqueEList<InstanceSpecification>()); + } + + public static void propagateAllocation(InstanceSpecification instance, EList<InstanceSpecification> nodes) { + // create copy of node (otherwise, more and more nodes get aggregated. + UniqueEList<InstanceSpecification> nodesCopy = new UniqueEList<InstanceSpecification>(); + nodesCopy.addAll(nodes); + nodesCopy.addAll(AllocUtils.getNodes(instance)); + for (Slot slot : instance.getSlots()) { + InstanceSpecification subInstance = DepUtils.getInstance(slot); + if (subInstance != null) { + if (DepUtils.isShared(slot)) { + for (InstanceSpecification node : nodesCopy) { + Log.log(Status.INFO, Log.DEPLOYMENT, String.format("Propagate node allocation: %s to %s", subInstance.getName(), node.getName())); //$NON-NLS-1$ + AllocUtils.allocate(subInstance, node); + } + } + else { + propagateAllocation(subInstance, nodesCopy); + } + } + } + } +} diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/UpdateDerivedInterfaces.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/UpdateDerivedInterfaces.java new file mode 100644 index 00000000000..1bec8c88131 --- /dev/null +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/UpdateDerivedInterfaces.java @@ -0,0 +1,51 @@ +/***************************************************************************** + * 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.designer.core.transformations; + +import org.eclipse.papyrus.qompass.designer.core.deployment.DepUtils; +import org.eclipse.papyrus.qompass.designer.core.sync.CompImplSync; +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.InstanceSpecification; +import org.eclipse.uml2.uml.Slot; + + +/** + * Update derived interfaces of ports. This is required, since the Copier does not follow references + * that are referenced via a derived attribute. Derived attributes are used for provided and required + * interfaces in the stereotype attributes of an FCM port. Thus, required (derived) interfaces would be + * unavailable in the copy, if not explicitly updated. + * However, the provided interface is not concerned as it appears in an "implements" relation. If the + * port is connected, the used interface of one port is the provided interface of the port counter part. + * Thus, the explicit update done by this function is not needed in most cases. + * + * see also FixTemplateSync (remove the latter?) + */ +public class UpdateDerivedInterfaces { + public static void updateIntfs(InstanceSpecification instance) { + Classifier cl = DepUtils.getClassifier(instance); + if (cl instanceof Class) { + Class implementation = (Class) cl; + CompImplSync.updatePorts(implementation); + CompImplSync.syncRealizations(implementation); + } + for (Slot slot : instance.getSlots()) { + InstanceSpecification subInstance = DepUtils.getInstance(slot); + if (!DepUtils.isShared(slot) && (subInstance != null)) { + updateIntfs(subInstance); + } + } + } +} diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/filters/FilterStateMachines.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/filters/FilterStateMachines.java index caa2cd88daa..1dd7b5ce874 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/filters/FilterStateMachines.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/filters/FilterStateMachines.java @@ -16,12 +16,14 @@ package org.eclipse.papyrus.qompass.designer.core.transformations.filters; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.qompass.designer.core.StUtils; import org.eclipse.papyrus.qompass.designer.core.listeners.CopyListener; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Element; import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; import org.eclipse.uml2.uml.Region; import org.eclipse.uml2.uml.StateMachine; import org.eclipse.uml2.uml.Transition; @@ -76,6 +78,11 @@ public class FilterStateMachines implements CopyListener { return; } Operation operation = tmClass.createOwnedOperation(newName, null, null); + for (Parameter parameter : effect.getOwnedParameters()) { + Parameter newParameter = EcoreUtil.copy(parameter); + operation.getOwnedParameters().add(newParameter); + StUtils.copyStereotypes(parameter, newParameter); + } copiedEffect.setSpecification(operation); copiedEffect.setName(newName); tmClass.getOwnedBehaviors().add(copiedEffect); |