diff options
Diffstat (limited to 'extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java')
-rw-r--r-- | extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/transformations/ContainerTrafo.java | 303 |
1 files changed, 189 insertions, 114 deletions
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; } |