diff options
author | Ansgar Radermacher | 2013-12-19 12:37:16 +0000 |
---|---|---|
committer | Ansgar Radermacher | 2013-12-19 13:03:17 +0000 |
commit | ac7745b1afa53790904ff31fb7487e46d9c2b841 (patch) | |
tree | 0aa400852b588b4b4eb29d099d6a03456fcd8bd8 /extraplugins | |
parent | 31a49b038fdaa69d2c88929e0a0e35321ad4c354 (diff) | |
download | org.eclipse.papyrus-ac7745b1afa53790904ff31fb7487e46d9c2b841.tar.gz org.eclipse.papyrus-ac7745b1afa53790904ff31fb7487e46d9c2b841.tar.xz org.eclipse.papyrus-ac7745b1afa53790904ff31fb7487e46d9c2b841.zip |
Bug 424442 - [QDesigner] Container transformation should separate rule application and instance creation
Diffstat (limited to 'extraplugins')
5 files changed, 306 insertions, 254 deletions
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 13a963f9f91..2d7d5c39eef 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 @@ -46,16 +46,6 @@ public abstract class AbstractContainerTrafo { */ protected static Map<Class, AbstractContainerTrafo> containers; - /** - * Only configure the instances, i.e. avoid re-creating elements of the container, but create - * the UML instance specifications - */ - public void configureOnly() { - configureOnly = true; - } - - protected boolean configureOnly; - public abstract void createContainer(Class smComponent, Class tmComponent) throws TransformationException; /** @@ -69,7 +59,7 @@ public abstract class AbstractContainerTrafo { * @param context * Additional information about the container that is used by instance configurators */ - public abstract void createContainerInstance(Class tmComponent, InstanceSpecification tmIS, ContainerContext context) + public abstract InstanceSpecification createContainerInstance(Class tmComponent, InstanceSpecification tmIS, ContainerContext context) throws TransformationException; /** @@ -88,34 +78,24 @@ public abstract class AbstractContainerTrafo { throws TransformationException; /** - * Move a slot from the executor instance specification to an instance - * specification of an extension/interceptor This is required, since the - * users cannot configure containers directly. The modification is done in - * the target model, i.e. the user model is not affected. - * - * Default implementation is empty - */ - public void moveSlots() { - } - - /** * The instance specification of the created container */ - protected InstanceSpecification containerIS; + // protected InstanceSpecification containerIS; /** - * Store source and target model + * Copy class from source to target model */ protected Copy copy; /** - * @return the instance specification of the created container + * Is called after a set of rule applications. + * Does nothing by default */ - public InstanceSpecification getContainerIS() { - return containerIS; + public void finalize() { } + /** * The created container implementation (prefixed with sm, since part of * source model) @@ -129,12 +109,12 @@ public abstract class AbstractContainerTrafo { protected Class tmClass; /** - * deployment plan within target model + * deployment plan within source model */ - protected Package tmCDP; - + protected Package smCDP; + /** - * Additional information about the container that is used by instance configurators + * deployment plan within target model */ - protected ContainerContext context; + protected Package tmCDP; } diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerContext.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerContext.java index 216e74ee31f..59839e5593f 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerContext.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerContext.java @@ -31,21 +31,31 @@ public class ContainerContext { * Convenience constructor. Used to initialize elements known outside the container transformation * itself * Constructor. - * - * @param executorPart - * @param nodeExecutorPart + * + * @param copy copier + * @param smIS original component in source model + * @param executorPart part representing the executor + * @param nodeExecutorPart allocation target (in case of HW model) */ - public ContainerContext(StructuralFeature executorPart, StructuralFeature nodeExecutorPart) { + public ContainerContext(Copy copy, InstanceSpecification smIS, StructuralFeature executorPart, StructuralFeature nodeExecutorPart) { + this.copy = copy; + this.smIS = smIS; this.smPartDF = executorPart; this.smNodePartDF = nodeExecutorPart; } /** + * original instance specification for a component in the source model. It might be used by instance configurators that need to access the + * configuration of the original component. + */ + public InstanceSpecification smIS; + + /** * The instance specification of the executor. It is a part of container that has been created, thus * an element of the target model. */ public InstanceSpecification executorIS; - + /** * The part within a composite that represents a component applying a container rule. It is * part of the source model. The main motivation for this information is that some instance configurators @@ -66,7 +76,9 @@ public class ContainerContext { /** * The port that is intercepted in case of an interceptor configuration. + * TODO: since container is *instantiated* after interception, port value is not useful */ public Port port; - + + public Copy copy; } 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 7626b23535c..d2aece79dd0 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 @@ -18,7 +18,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.util.EcoreUtil; @@ -27,7 +26,6 @@ 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.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.StUtils; @@ -35,6 +33,7 @@ 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.extensions.InstanceConfigurator; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateInstantiation; import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils; @@ -44,9 +43,11 @@ import org.eclipse.uml2.uml.Class; import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Connector; import org.eclipse.uml2.uml.ConnectorEnd; +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; @@ -54,6 +55,8 @@ import org.eclipse.uml2.uml.TemplateBinding; import org.eclipse.uml2.uml.TemplateSignature; import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.UMLPackage; +import org.eclipse.uml2.uml.ValueSpecification; +import org.eclipse.uml2.uml.VisibilityKind; import org.eclipse.uml2.uml.util.UMLUtil; /** @@ -78,10 +81,11 @@ public class ContainerTrafo extends AbstractContainerTrafo { * @param tmCDP * deployment plan within target model */ - public ContainerTrafo(Copy copy, Package tmCDP) { + public ContainerTrafo(Copy copy, Package tmCDP, InstanceSpecification executorIS) { this.copy = copy; this.tmCDP = tmCDP; - configureOnly = false; + this.executorIS = executorIS; + portInfo = new HashMap<Property, Port>(); } /** @@ -114,18 +118,20 @@ public class ContainerTrafo extends AbstractContainerTrafo { // model. Yet code generation works, as port names are identical for(Port port : PortUtils.getAllPorts(tmComponent)) { // copy port - Port newPort = EcoreUtil.copy(port); // don't use E3CM copy, since this is not a copy from source to target model - tmContainerImpl.getOwnedAttributes().add(newPort); - StUtils.copyStereotypes(port, newPort); - - // create delegation for application port - Connector containerDelegation = tmContainerImpl.createOwnedConnector("delegation " + port.getName()); //$NON-NLS-1$ - Copy.copyID(tmContainerImpl, containerDelegation); - ConnectorEnd end1 = containerDelegation.createEnd(); - end1.setRole(newPort); - ConnectorEnd end2 = containerDelegation.createEnd(); - end2.setPartWithPort(executorPart); - end2.setRole(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 + tmContainerImpl.getOwnedAttributes().add(newPort); + StUtils.copyStereotypes(port, newPort); + + // create delegation for application port + Connector containerDelegation = tmContainerImpl.createOwnedConnector("delegation " + port.getName()); //$NON-NLS-1$ + Copy.copyID(tmContainerImpl, containerDelegation); + ConnectorEnd end1 = containerDelegation.createEnd(); + end1.setRole(newPort); + ConnectorEnd end2 = containerDelegation.createEnd(); + end2.setPartWithPort(executorPart); + end2.setRole(port); + } } // Inheritance issues: @@ -171,32 +177,62 @@ public class ContainerTrafo extends AbstractContainerTrafo { * Additional information about the container that is used by instance configurators */ @Override - public void createContainerInstance(Class tmComponent, InstanceSpecification tmIS, ContainerContext context) throws TransformationException { + public InstanceSpecification createContainerInstance(Class tmComponent, InstanceSpecification tmIS, ContainerContext context) throws TransformationException { // create an instance specification for the container - containerIS = (InstanceSpecification)tmCDP.createPackagedElement(tmIS.getName(), UMLPackage.eINSTANCE.getInstanceSpecification()); + InstanceSpecification containerIS = + (InstanceSpecification)tmCDP.createPackagedElement(tmIS.getName(), UMLPackage.eINSTANCE.getInstanceSpecification()); // assign new name to original instance specification which reflects // role within containment hierarchy tmIS.setName(tmIS.getName() + "." + executorPartName); //$NON-NLS-1$ containerIS.getClassifiers().add(tmContainerImpl); // existing instance specification (tmIS) is the executor instance specification DepCreation.createSlot(containerIS, tmIS, executorPart); - executorIS = tmIS; counter = 0; // containers.put(tmComponent, this); - this.context = context; - context.executorIS = executorIS; + context.executorIS = tmIS; + EList<Slot> connectorSlots = new BasicEList<Slot>(); // now create instances for the contained elements for(Property extensionPart : tmContainerImpl.getAttributes()) { Type tmContainerExtImpl = extensionPart.getType(); if(tmContainerExtImpl instanceof Class) { - InstanceSpecification containerExtIS = DepCreation.createDepPlan(tmCDP, (Class)tmContainerExtImpl, containerIS.getName() + "." + //$NON-NLS-1$ - extensionPart.getName(), false); - // configure extension - InstanceConfigurator.configureInstance(containerExtIS, extensionPart, null); - DepCreation.createSlot(containerIS, containerExtIS, extensionPart); + if (DepUtils.getSlot(executorIS, 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$ + } + if (containerExtIS == null) { + containerExtIS = DepCreation.createDepPlan(tmCDP, (Class)tmContainerExtImpl, isName, false); + } + // configure extension + context.port = portInfo.get(extensionPart); + InstanceConfigurator.configureInstance(containerExtIS, extensionPart, context); + Slot partSlot = DepCreation.createSlot(containerIS, containerExtIS, extensionPart); + if (StereotypeUtil.isApplied(tmContainerExtImpl, InteractionComponent.class)) { + connectorSlots.add(partSlot); + } + } } - } + } + + // handle propagation of node allocation for connectors. Do that in 2nd loop, since the allocation + // of parts might be incomplete before. + for(Slot connectorSlot : connectorSlots) { + ConnectorReification.propagateNodeAllocation(tmContainerImpl, containerIS, connectorSlot); + } + moveSlots(executorIS); + return containerIS; } /** @@ -205,17 +241,27 @@ public class ContainerTrafo extends AbstractContainerTrafo { * @param tmComponent * @param tmIS */ - public void createHwContainerInstance(Class tmComponent, InstanceSpecification tmNode, ContainerContext context) { + public InstanceSpecification createHwContainerInstance(Class tmComponent, InstanceSpecification tmNode, ContainerContext context) { // create an instance specification for the container - containerIS = (InstanceSpecification)tmCDP.createPackagedElement(tmNode.getName() + hwContainerPostfix, UMLPackage.eINSTANCE.getInstanceSpecification()); + InstanceSpecification containerIS = + (InstanceSpecification)tmCDP.createPackagedElement(tmNode.getName() + hwContainerPostfix, UMLPackage.eINSTANCE.getInstanceSpecification()); // assign new name to original instance specification which reflects // role within containment hierarchy containerIS.getClassifiers().add(tmContainerImpl); // containers.put(tmComponent, this); counter = 0; executorIS = tmNode; - this.context = context; context.executorIS = executorIS; + // copy slots from HW instance specification + for (Slot slot : tmNode.getSlots()) { + Slot slotCopy = containerIS.createSlot(); + slotCopy.setDefiningFeature(slot.getDefiningFeature()); + // copy values (use CopyTo.copyTo(slot, containerIS) instead?) + for (ValueSpecification value : slot.getValues()) { + Copy.copyValue(value, slotCopy); + } + } + return containerIS; } /** @@ -283,7 +329,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { } else { Property extensionPart = - expandAggregationExtension(part.getName(), extOrInterceptor, tmComponent); + expandAggregationExtension(part, extOrInterceptor, tmComponent); // register relation to facilitate connector copy copy.setPackageTemplate(smContainerRule.getBase_Class(), tmContainerImpl); copy.putPair(part, extensionPart); @@ -325,7 +371,7 @@ public class ContainerTrafo extends AbstractContainerTrafo { org.eclipse.papyrus.FCM.Connector fcmConn = StUtils.getConnector(connector); if(fcmConn != null) { ConnectorReification.reifyConnector(copy, tmContainerImpl, - UMLTool.varName(connector), connector, containerIS, null); + UMLTool.varName(connector), connector, executorIS, null); } else { copy.remove(connector); @@ -342,42 +388,31 @@ public class ContainerTrafo extends AbstractContainerTrafo { * application component also inherits from the type of the container * extension in order to avoid copying ports. */ - Property expandAggregationExtension(String name, Class smContainerExtImpl, Class tmComponent) throws TransformationException { + Property expandAggregationExtension(Property smExtensionPart, Class smContainerExtImpl, Class tmComponent) throws TransformationException { Property extensionPart; + String name = smExtensionPart.getName(); Class tmContainerExtImpl = null; - if(configureOnly) { - extensionPart = tmContainerImpl.getAttribute(name, null); - if((extensionPart != null) && extensionPart.getType() instanceof Class) { - tmContainerExtImpl = (Class)extensionPart.getType(); - } + + TemplateSignature signature = TemplateUtils.getSignature(smContainerExtImpl); + 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); + Object[] args = new Object[]{}; + TemplateInstantiation ti = new TemplateInstantiation(copy, binding, args); + tmContainerExtImpl = (Class)ti.bindNamedElement(smContainerExtImpl); } - else { - TemplateSignature signature = TemplateUtils.getSignature(smContainerExtImpl); - 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); - Object[] args = new Object[]{}; - TemplateInstantiation ti = new TemplateInstantiation(copy, binding, args); - tmContainerExtImpl = (Class)ti.bindNamedElement(smContainerExtImpl); - } - // add part associated with the extension to the container - extensionPart = tmContainerImpl.createOwnedAttribute(name, tmContainerExtImpl); - } - // problem: would not be unique in case of multiple extensions - // Copy.copyID(tmComponent, extensionPart, "a"); - extensionPart.setIsComposite(true); - // TODO separation of container creation and instance creation - InstanceSpecification containerExtIS = DepCreation.createDepPlan(tmCDP, tmContainerExtImpl, containerIS.getName() + "." + extensionPart.getName(), false); //$NON-NLS-1$ - // configure extension - context.port = null; - InstanceConfigurator.configureInstance(containerExtIS, extensionPart, context); - DepCreation.createSlot(containerIS, containerExtIS, extensionPart); + // add part associated with the extension to the container + extensionPart = tmContainerImpl.createOwnedAttribute(name, tmContainerExtImpl); + // Copy.copyID(tmComponent, extensionPart, "a"); + extensionPart.setAggregation(smExtensionPart.getAggregation()); + Copy.copyMultElemModifiers(smExtensionPart, extensionPart); + Copy.copyFeatureModifiers(smExtensionPart, extensionPart); return extensionPart; } @@ -421,53 +456,37 @@ public class ContainerTrafo extends AbstractContainerTrafo { Property connectorPart; String interceptionName = interceptorName + port.getName() + counter; - if(configureOnly) { - // counter is reset before instance configuration - connectorPart = tmContainerImpl.getAttribute(interceptionName, null); - } - else { - Connector interceptionConnector = null; - // get delegation connector - for(Connector connector : tmContainerImpl.getOwnedConnectors()) { - if(ConnectorUtils.connectsPort(connector, port)) { - interceptionConnector = connector; - break; - } - } - // interceptionConnector = tmContainerImpl.getOwnedConnector - // ("delegation " + port.getName ()); - if(interceptionConnector == null) { - throw new TransformationException(Messages.ContainerTrafo_CannotFindDelegationConn); + Connector interceptionConnector = null; + // get delegation connector + for(Connector connector : tmContainerImpl.getOwnedConnectors()) { + if(ConnectorUtils.connectsPort(connector, port)) { + interceptionConnector = connector; + break; } - - interceptionConnector.setName(interceptorName + port.getName() + counter); - 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); - - // pass target component and port to interceptor (not clean, define - // suitable template signature as for instance in methodCall_comp - Object[] args = new Object[]{ executorIS, port }; - TransformationContext.instance = executorIS; - TransformationContext.port = port; - connectorPart = ConnectorReification.reifyConnector(copy, tmContainerImpl, UMLTool.varName(interceptionConnector), interceptionConnector, executorIS, args); - connectorParts.add(connectorPart); - TransformationContext.port = null; - // delete intermediate connector (has been replaced by two - // connections to the reified connector) - interceptionConnector.destroy(); } - // Now create an instance specification for the reified connector - InstanceSpecification reifiedConnectorIS = DepCreation.createDepPlan(tmCDP, (Class)connectorPart.getType(), - containerIS.getName() + "." + interceptionName, false); //$NON-NLS-1$ - // configure connector - context.port = port; - InstanceConfigurator.configureInstance(reifiedConnectorIS, connectorPart, context); - - Slot partSlot = DepCreation.createSlot(containerIS, reifiedConnectorIS, connectorPart); - + // interceptionConnector = tmContainerImpl.getOwnedConnector + // ("delegation " + port.getName ()); + if(interceptionConnector == null) { + throw new TransformationException(Messages.ContainerTrafo_CannotFindDelegationConn); + } - ConnectorReification.propagateNodeAllocation(tmComponent, executorIS, partSlot); + interceptionConnector.setName(interceptorName + port.getName() + counter); + 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); + + // pass target component and port to interceptor (not clean, define + // suitable template signature as for instance in methodCall_comp + Object[] args = new Object[]{ executorIS, port }; + TransformationContext.instance = executorIS; + TransformationContext.port = port; + connectorPart = ConnectorReification.reifyConnector(copy, tmContainerImpl, UMLTool.varName(interceptionConnector), interceptionConnector, executorIS, args); + connectorParts.add(connectorPart); + TransformationContext.port = null; + portInfo.put(connectorPart, port); + // delete intermediate connector (has been replaced by two + // connections to the reified connector) + interceptionConnector.destroy(); } counter++; return connectorParts; @@ -475,12 +494,21 @@ public class ContainerTrafo extends AbstractContainerTrafo { /** * Move a slot from the executor instance specification to an instance - * specification of an extension/interceptor This is required, since the + * specification of an extension/interceptor. This is required, since * users cannot configure containers directly. The modification is done in * the target model, i.e. the user model is not affected. + * + * Configuration is based on the idea that we can have multiple classifiers for an + * instance specification and that we add additional slots for attributes of the 2nd + * classifier which becomes "visible" after container transformation. + * Main use: configure priority of thread within container. + * + * TODO: Not clear, whether we should keep this operation, since configuration of elements that are not + * (directly) part of the user model is confusing. Application was: configuration + * of thread priorities within container. */ - public void moveSlots() { - Log.log(Status.INFO, Log.TRAFO_CONTAINER, String.format(Messages.ContainerTrafo_InfoMoveSlots, executorIS.getQualifiedName())); + public void moveSlots(InstanceSpecification containerIS) { + // Log.log(Status.INFO, Log.TRAFO_CONTAINER, String.format(Messages.ContainerTrafo_InfoMoveSlots, executorIS.getQualifiedName())); Classifier mainCl = DepUtils.getClassifier(executorIS); Iterator<Slot> slotIt = executorIS.getSlots().iterator(); while(slotIt.hasNext()) { @@ -546,27 +574,74 @@ public class ContainerTrafo extends AbstractContainerTrafo { } } + @Override + public void finalize() { + discoverServices(); + } + + /** + * Connector ports of executor with compatible ports offered by container extensions + * (runtime system) + */ + public void discoverServices() { + Type executorType = executorPart.getType(); + if (!(executorType instanceof EncapsulatedClassifier)) { + return; + } + EncapsulatedClassifier ec = (EncapsulatedClassifier) executorType; + for (Port executorPort : ec.getOwnedPorts()) { + for (Property svcPart : tmContainerImpl.getOwnedAttributes()) { + if (svcPart == executorPart) { + continue; + } + Type containerSvcType = svcPart.getType(); + if (containerSvcType instanceof EncapsulatedClassifier) { + EncapsulatedClassifier containerSvc = (EncapsulatedClassifier) containerSvcType; + for (Port svcPort : containerSvc.getOwnedPorts()) { + if (PortUtils.matches(executorPort, svcPort, true)) { + // create connector + Connector c = tmContainerImpl.createOwnedConnector("auto"); //$NON-NLS-1$ + ConnectorEnd ce1 = c.createEnd(); + ConnectorEnd ce2 = c.createEnd(); + ce1.setPartWithPort(executorPart); + ce1.setRole(executorPort); + ce2.setPartWithPort(svcPart); + ce2.setRole(svcPort); + } + } + } + } + } + } + /** * The attribute within the container that holds the executor, i.e. the * original component */ - private Property executorPart; + protected Property executorPart; /** * An instance specification of the executor in the target model (todo: should be source model instead?), i.e. * of the component before container expansion */ - private InstanceSpecification executorIS; + protected InstanceSpecification executorIS; /** * The created container implementation (prefixed with tm, since part of * target model) */ - private Class tmContainerImpl; + protected Class tmContainerImpl; /** * A counter which is used to manage unique names for interceptors (if * multiple interceptors are applied) */ - private int counter; + protected int counter; + + /** + * Store information about intercepted port. The map contains a mapping from the part representing + * a reified connector to the port that was intercepted. It is stored, since it might be used by instance + * configurators that configure the container instance. + */ + protected Map<Property, Port> portInfo; } 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 c43533ba967..b59434d7cf3 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 @@ -77,7 +77,6 @@ public class LWContainerTrafo extends AbstractContainerTrafo { public LWContainerTrafo(Copy copy, Package tmCDP) { this.copy = copy; this.tmCDP = tmCDP; - configureOnly = false; interceptionOpMap = new HashMap<Operation, Operation>(); } @@ -116,14 +115,6 @@ public class LWContainerTrafo extends AbstractContainerTrafo { operations = new BasicEList<Operation>(smClass.getAllOperations()); } - /** - * Only configure the instances, i.e. avoid re-creating elements of the container, but create - * the UML instance specifications - */ - public void configureOnly() { - configureOnly = true; - } - public void createInstance() { } @@ -263,26 +254,14 @@ public class LWContainerTrafo extends AbstractContainerTrafo { * extension in order to avoid copying ports. */ Property expandAggregationExtension(String name, Class smContainerExtImpl, Class tmComponent) throws TransformationException { - Property extensionPart; - Class tmContainerExtImpl = null; - if(configureOnly) { - extensionPart = tmClass.getAttribute(name, null); - if((extensionPart != null) && extensionPart.getType() instanceof Class) { - tmContainerExtImpl = (Class)extensionPart.getType(); - } - } - else { - tmContainerExtImpl = expandAggregationDep(smContainerExtImpl, tmComponent); + Class tmContainerExtImpl = expandAggregationDep(smContainerExtImpl, tmComponent); + + // add part associated with the extension to the container + Property extensionPart = tmClass.createOwnedAttribute(name, tmContainerExtImpl); - // add part associated with the extension to the container - extensionPart = tmClass.createOwnedAttribute(name, tmContainerExtImpl); - } // problem: would not be unique in case of multiple extensions // Copy.copyID(tmComponent, extensionPart, "a"); extensionPart.setIsComposite(true); - // TODO separation of container creation and instance creation - // configure extension - // InstanceConfigurator.configureInstance(containerIS, extensionPart, context); return extensionPart; } @@ -364,11 +343,13 @@ public class LWContainerTrafo extends AbstractContainerTrafo { protected Map<Operation, Operation> interceptionOpMap; + /** + * @see AbstractContainerTrafo.createContainerInstance + */ @Override - public void createContainerInstance(Class tmComponent, InstanceSpecification tmIS, ContainerContext context) throws TransformationException { - containerIS = tmIS; - this.context = context; - this.context.executorIS = tmIS; + public InstanceSpecification createContainerInstance(Class tmComponent, InstanceSpecification executorIS, ContainerContext context) throws TransformationException { + InstanceSpecification containerIS = executorIS; + context.executorIS = executorIS; // TODO ... incomplete! // InstanceConfigurator.configureInstance(smContainerRule, containerIS, null, context); @@ -376,16 +357,17 @@ public class LWContainerTrafo extends AbstractContainerTrafo { for(Property extensionPart : tmComponent.getAttributes()) { Type tmContainerExtImpl = extensionPart.getType(); if(tmContainerExtImpl instanceof Class) { - if (DepUtils.getSlot(tmIS, extensionPart) == null) { + if (DepUtils.getSlot(executorIS, extensionPart) == null) { // no slot for part exists => assume that the part has been added by the container and create an instance specification for it. - } - InstanceSpecification containerExtIS = DepCreation.createDepPlan(tmCDP, (Class)tmContainerExtImpl, containerIS.getName() + "." + //$NON-NLS-1$ + InstanceSpecification containerExtIS = DepCreation.createDepPlan(tmCDP, (Class)tmContainerExtImpl, containerIS.getName() + "." + //$NON-NLS-1$ extensionPart.getName(), false); - // configure extension - InstanceConfigurator.configureInstance(containerExtIS, extensionPart, null); - DepCreation.createSlot(containerIS, containerExtIS, extensionPart); + // configure extension + InstanceConfigurator.configureInstance(containerExtIS, extensionPart, null); + DepCreation.createSlot(containerIS, containerExtIS, extensionPart); + } } - } + } + return containerIS; } } 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 e01632bd9a4..f9a2d26ba26 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 @@ -203,14 +203,9 @@ public class MainModelTrafo { // the method createContainerInstance must be called for each instance of the application component // (caveat: don't mix-up with instance of Java classes of the development tool) // TODO: since we support multiple container kinds, we need to keep their container map separate! - if(containerTrafo != null) { - // create instance, if container exists already (if a container exists, all instances are - // instances of the container - containerTrafo.configureOnly(); - containerTrafo.createContainerInstance(tmComponent, tmIS, new ContainerContext(smDF, null)); - } - else { - // process container rules + InstanceSpecification containerIS = null; + 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)) @@ -219,26 +214,36 @@ public class MainModelTrafo { containerTrafo = new LWContainerTrafo(copy, tmCDP); } else { - containerTrafo = new ContainerTrafo(copy, tmCDP); + containerTrafo = new ContainerTrafo(copy, tmCDP, tmIS); } - // create container instance once for all rules (that use same container kind) containerTrafo.createContainer(smComponent, tmComponent); - containerTrafo.createContainerInstance(tmComponent, tmIS, new ContainerContext(smDF, null)); } else { // configure only?? } containerTrafo.applyRule(rule, smComponent, tmComponent); } - // TODO(?) check if rule has already been applied (don't mix-up instances/classes) + } + if (containerTrafo != null) { + containerTrafo.finalize(); } } + if (containerTrafo != null) { + // create instance of container. This is done after rule application, since + // elements that are added by the rules need to be instantiated as well. + // TODO: Cannot mix both rules. + containerIS = containerTrafo.createContainerInstance(tmComponent, tmIS, new ContainerContext(copy, smIS, smDF, null)); + } + // ------------------- end of container handling of SW nodes + // copy node allocation for(InstanceSpecification smNode : AllocUtils.getNodes(smIS)) { InstanceSpecification tmNode = copy.getCopy(smNode); AllocUtils.allocate(tmIS, tmNode); if(!nodeHandled.containsKey(tmNode)) { + // check if node (on an instance level) has already been treated. This is required, since many + // instances might be allocated to the same node. nodeHandled.put(tmNode, true); // check, whether a container rule is applied on the tmNode @@ -249,65 +254,58 @@ public class MainModelTrafo { if(hwRules.size() > 0) { - AbstractContainerTrafo abstractNodeContainerTrafo = ContainerTrafo.get((Class)tmCS); - if(abstractNodeContainerTrafo instanceof ContainerTrafo) { - - ContainerTrafo nodeContainerTrafo = (ContainerTrafo)abstractNodeContainerTrafo; - // make copy of inheritedRule list (avoid that added elements remain in single rule list passed to all) - - // issues - // - unlike SW component container, don't update references pointing towards the HW node - // - create additional part in system (top-level) component for the node container - // - container (_cc class) appears in platform component (same package as HW node) - // - port copying and creation of delegation connectors does not make much sense, creation of - // executor itself does not make much sense, additional operation "createHwContainer" - - // obtain property related to node instance - Slot smNodeSlot = DepUtils.getParentSlot(smNode); - ContainerContext context = new ContainerContext(smDF, smNodeSlot != null ? smNodeSlot.getDefiningFeature() : null); - - if(nodeContainerTrafo != null) { - // only create instance, if container exists already - nodeContainerTrafo.configureOnly(); - nodeContainerTrafo.createHwContainerInstance(tmComponent, tmNode, context); - } - - Package smCDP = smIS.getNearestPackage(); - DeploymentPlan smFCM_CDP = UMLUtil.getStereotypeApplication(smCDP, DeploymentPlan.class); - + ContainerTrafo nodeContainerTrafo = (ContainerTrafo) ContainerTrafo.get((Class)tmCS); + + // issues + // - unlike SW component container, don't update references pointing towards the HW node + // - create additional part in system (top-level) component for the node container + // - container (_cc class) appears in platform component (same package as HW node) + // - port copying and creation of delegation connectors does not make much sense, creation of + // executor itself does not make much sense, additional operation "createHwContainer" + + // obtain property related to node instance + Slot smNodeSlot = DepUtils.getParentSlot(smNode); + ContainerContext context = new ContainerContext(copy, smIS, smDF, smNodeSlot != null ? smNodeSlot.getDefiningFeature() : null); + Package smCDP = smIS.getNearestPackage(); + DeploymentPlan smFCM_CDP = UMLUtil.getStereotypeApplication(smCDP, DeploymentPlan.class); + + if(nodeContainerTrafo == null) { + // container does not exist, check rules and create eventually for(ContainerRule rule : hwRules) { if(RuleManagement.isRuleActive(rule)) { if(nodeContainerTrafo == null) { // at least one active rule => create container (or get previously instantiated)) - nodeContainerTrafo = new ContainerTrafo(copy, tmCDP); + nodeContainerTrafo = new ContainerTrafo(copy, tmCDP, tmIS); nodeContainerTrafo.createHwContainer((Class)tmCS); - nodeContainerTrafo.createHwContainerInstance(tmComponent, tmNode, context); - } - nodeContainerTrafo.applyRule(rule, smComponent, tmComponent); - - // now add attribute in system (obtain via classifier of main instance in smCDP) - if(smFCM_CDP != null) { - InstanceSpecification smMI = smFCM_CDP.getMainInstance(); - Classifier smSystem = DepUtils.getClassifier(smMI); - Classifier tmSystem = copy.getCopy(smSystem); - InstanceSpecification tmMI = DepUtils.getInstanceForClassifier(tmCDP, tmSystem); - if(tmSystem instanceof Class) { - Property hwcPart = - ((Class)tmSystem).createOwnedAttribute(smNode.getName() + HW_COMP_PREFIX, nodeContainerTrafo.getContainer()); - // and now create a slot for the created instance. - DepPlanUtils.createSlot(tmCDP, tmMI, nodeContainerTrafo.getContainerIS(), hwcPart); - } + nodeContainerTrafo.applyRule(rule, smComponent, tmComponent); } - - // now allocate instance - AllocUtils.allocate(nodeContainerTrafo.getContainerIS(), tmNode); } } } + if (nodeContainerTrafo != null) { + InstanceSpecification hwContainerIS = + nodeContainerTrafo.createHwContainerInstance(tmComponent, tmNode, context); + // now add attribute in system (obtain via classifier of main instance in smCDP) + if(smFCM_CDP != null) { + InstanceSpecification smMI = smFCM_CDP.getMainInstance(); + Classifier smSystem = DepUtils.getClassifier(smMI); + Classifier tmSystem = copy.getCopy(smSystem); + InstanceSpecification tmMI = DepUtils.getInstanceForClassifier(tmCDP, tmSystem); + if(tmSystem instanceof Class) { + Property hwcPart = + ((Class)tmSystem).createOwnedAttribute(smNode.getName() + HW_COMP_PREFIX, nodeContainerTrafo.getContainer()); + // and now create a slot for the created instance. + DepPlanUtils.createSlot(tmCDP, tmMI, hwContainerIS, hwcPart); + } + + // now allocate instance + AllocUtils.allocate(hwContainerIS, tmNode); + } + } } } } - } // ------------------- handling of HW nodes + } // ------------------- end of container handling of HW nodes // reread instName (may have been changed by container transformation). @@ -418,13 +416,13 @@ public class MainModelTrafo { */ } - // configure connector - InstanceConfigurator.configureInstance(tmReifiedConnectorIS, connectorPart, null); - Slot partSlot = DepCreation.createSlot(tmIS, tmReifiedConnectorIS, connectorPart); ConnectorReification.propagateNodeAllocation(tmComponent, tmIS, partSlot); + + // configure connector + InstanceConfigurator.configureInstance(tmReifiedConnectorIS, connectorPart, null); } } } @@ -444,10 +442,9 @@ public class MainModelTrafo { AllocTransfo at = new AllocTransfo(); at.transformAllocs(copy, tmComponent); - if(containerTrafo != null) { + if(containerIS != null) { // return containerIS - containerTrafo.moveSlots(); - return containerTrafo.getContainerIS(); + return containerIS; } else { return tmIS; } @@ -455,7 +452,13 @@ public class MainModelTrafo { protected Map<InstanceSpecification, Boolean> nodeHandled; - protected Copy copy; + /** + * Copier from source to target model + */ + protected Copy copy; + /** + * deployment plan within target model + */ protected Package tmCDP; } |