diff options
author | Ansgar Radermacher | 2014-01-08 15:53:20 +0000 |
---|---|---|
committer | Ansgar Radermacher | 2014-01-08 16:28:07 +0000 |
commit | 33db97ea2615ef7f63e9cd404a4825f811e90d9d (patch) | |
tree | b8803fb8766c9627674f295b1dd2dbd8c654fcc6 /extraplugins | |
parent | 929a1c0c63c5cfc5f0f58bfa5b976812b5b5cd08 (diff) | |
download | org.eclipse.papyrus-33db97ea2615ef7f63e9cd404a4825f811e90d9d.tar.gz org.eclipse.papyrus-33db97ea2615ef7f63e9cd404a4825f811e90d9d.tar.xz org.eclipse.papyrus-33db97ea2615ef7f63e9cd404a4825f811e90d9d.zip |
- Bug 424759 - [QDesginer] Need for more options when binding templates
Diffstat (limited to 'extraplugins')
11 files changed, 399 insertions, 264 deletions
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 new file mode 100644 index 00000000000..67aedf7fa24 --- /dev/null +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/BindingUtils.java @@ -0,0 +1,134 @@ +/***************************************************************************** + * 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.templates; + +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.papyrus.C_Cpp.ConstInit; +import org.eclipse.papyrus.qompass.designer.core.Messages; +import org.eclipse.papyrus.qompass.designer.core.PortUtils; +import org.eclipse.papyrus.qompass.designer.core.acceleo.AcceleoDriverWrapper; +import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; +import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext; +import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.Interface; +import org.eclipse.uml2.uml.NamedElement; +import org.eclipse.uml2.uml.OpaqueBehavior; +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.Parameter; +import org.eclipse.uml2.uml.Port; +import org.eclipse.uml2.uml.Type; +import org.eclipse.uml2.uml.util.UMLUtil; + +public class BindingUtils { + + public static Operation instantiateOperation(Copy copy, Element actual, Operation operation, Class boundClass) { + try { + Operation newOperation = copy.getCopy(operation); + if(actual instanceof Operation) { + for(Parameter parameter : ((Operation)actual).getOwnedParameters()) { + Parameter newParam = EcoreUtil.copy(parameter); // copy parameter via EcoreUtil + newParam.setType(copy.getCopy(parameter.getType())); + newOperation.getOwnedParameters().add(newParam); + } + } + TransformationContext.classifier = newOperation.getClass_(); + if(actual instanceof Classifier) { + bindOperation(newOperation, (Classifier)actual); + } + String newName = AcceleoDriverWrapper.evaluate(operation.getName(), actual, null); + newOperation.setName(newName); + + return newOperation; + } catch (TransformationException e) { + // throw runtime exception + throw new RuntimeException(String.format(Messages.TemplateInstantiationListener_TrafoException, e.getMessage())); + } + } + + /** + * Instantiate a behavior + * @param copy copier + * @param actual actual in template instantiation + * @param opaqueBehavior behavior with body in form of an Acceleo template. + * @return instantiated (bound) behavior. + * @throws TransformationException + */ + public static OpaqueBehavior instantiateBehavior(Copy copy, Element actual, OpaqueBehavior opaqueBehavior) throws TransformationException { + OpaqueBehavior newBehavior = copy.getCopy(opaqueBehavior); + if(actual instanceof NamedElement) { + String newName = AcceleoDriverWrapper.evaluate(opaqueBehavior.getName(), actual, null); + newBehavior.setName(newName); + } + EList<String> bodyList = newBehavior.getBodies(); + for(int i = 0; i < bodyList.size(); i++) { + String body = bodyList.get(i); + TransformationContext.classifier = (Classifier)newBehavior.getOwner(); + // pass qualified operation name as template name. Used to identify script in case of an error + String newBody = AcceleoDriverWrapper.evaluate(body, newBehavior.getQualifiedName(), actual, null); + bodyList.set(i, newBody); + } + return newBehavior; + } + + + + /** + * Bind C++ const initializer + * + * @param operation + * @param actual + * @throws TransformationException + */ + public static void bindOperation(Operation operation, Classifier actual) throws TransformationException { + // perform binding in case of C++ initializer + ConstInit cppConstInit = UMLUtil.getStereotypeApplication(operation, ConstInit.class); + if(cppConstInit != null) { + // TODO: specific to C++ + String init = cppConstInit.getInitialisation(); + String newInit = AcceleoDriverWrapper.bind(init, actual); + cppConstInit.setInitialisation(newInit); + } + } + + /** + * @param actual + * the actual template parameter + * @param boundClass + * the bound class + * @param provides + * true, if the provided interface should be returned + * @return the provided or required interface of a port (of the passed + * boundClass) that is typed with the the actual. + */ + public static Interface getInterfaceFromPortTypedWithActual(Type actual, Class boundClass, boolean provided) { + for(Port port : PortUtils.getAllPorts(boundClass)) { + Interface provOrReqIntf; + if(provided) { + provOrReqIntf = PortUtils.getProvided(port); + } else { + provOrReqIntf = PortUtils.getRequired(port); + } + + if((port.getType() == actual) && (provOrReqIntf != null)) { + return provOrReqIntf; + } + } + return null; + } +} diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppInclude.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppInclude.java index f06a2b50ae9..4fcbc12df1f 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppInclude.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppInclude.java @@ -49,9 +49,9 @@ public class InstantiateCppInclude implements CopyListener { // TODO: C++ specific code! Classifier targetCl = (Classifier)targetEObj; try { - Classifier actual = TemplateInstantiationListener.getFirstActualFromBinding(binding, targetCl); - if(actual != null) { - Include cppInclude = UMLUtil.getStereotypeApplication(targetCl, Include.class); + Classifier actual = TemplateUtils.getFirstActualFromBinding(binding); + Include cppInclude = UMLUtil.getStereotypeApplication(targetCl, Include.class); + if((actual != null) && (cppInclude != null)) { TransformationContext.classifier = targetCl; String newBody = AcceleoDriverWrapper.evaluate(cppInclude.getBody(), actual, null); String newPreBody = AcceleoDriverWrapper.evaluate(cppInclude.getPreBody(), actual, null); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppIncludeWOB.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppIncludeWOB.java index 9841e7d8555..85f5766d599 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppIncludeWOB.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/InstantiateCppIncludeWOB.java @@ -17,7 +17,6 @@ package org.eclipse.papyrus.qompass.designer.core.templates; import org.eclipse.emf.ecore.EObject; import org.eclipse.papyrus.C_Cpp.Include; import org.eclipse.papyrus.FCM.Template; -import org.eclipse.papyrus.FCM.TemplateKind; import org.eclipse.papyrus.qompass.designer.core.acceleo.AcceleoDriverWrapper; import org.eclipse.papyrus.qompass.designer.core.listeners.CopyListener; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; @@ -50,7 +49,7 @@ public class InstantiateCppIncludeWOB implements CopyListener { Classifier targetCl = (Classifier)targetEObj; Template template = UMLUtil.getStereotypeApplication(targetCl, Template.class); // apply, in case of pass-classifier - if((template != null) && (template.getKind() == TemplateKind.PASS_CLASSIFIER)) { + if((template != null) && (template.getHelper() == null)) { try { Include cppInclude = UMLUtil.getStereotypeApplication(targetCl, Include.class); TransformationContext.classifier = targetCl; diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiation.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiation.java index 36ee99a3941..dd7ec368b62 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiation.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.designer.core/src/org/eclipse/papyrus/qompass/designer/core/templates/TemplateInstantiation.java @@ -15,8 +15,8 @@ package org.eclipse.papyrus.qompass.designer.core.templates; import org.eclipse.emf.common.util.EList; +import org.eclipse.papyrus.FCM.BindingHelper; import org.eclipse.papyrus.FCM.Template; -import org.eclipse.papyrus.FCM.TemplateKind; import org.eclipse.papyrus.qompass.designer.core.Messages; import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationContext; @@ -54,6 +54,13 @@ public class TemplateInstantiation { this(copy, binding, null); } + /** + * + * @param copy_ copier + * @param binding UML template binding + * @param args currently unused + * @throws TransformationException + */ public TemplateInstantiation(final Copy copy_, final TemplateBinding binding, Object args[]) throws TransformationException { if(binding == null) { // user should never see this exception @@ -124,6 +131,7 @@ public class TemplateInstantiation { if(!copy.postCopyListeners.contains(FixTemplateSync.getInstance())) { copy.postCopyListeners.add(FixTemplateSync.getInstance()); } + // TODO: programming language specific code!! InstantiateCppInclude.getInstance().init(binding, args); if(!copy.postCopyListeners.contains(InstantiateCppInclude.getInstance())) { @@ -137,7 +145,6 @@ public class TemplateInstantiation { * TODO: A more efficient way would be to cache the copy function and only re-sync, if a new model has been loaded. * On the other hand, the bound package is normally not very large * - * @param copy A copy map * @param sourcePkg The package template (source) * @param targetPkg The bound package (target) */ @@ -196,10 +203,10 @@ public class TemplateInstantiation { Package boundPackage = (Package)binding.getBoundElement(); EList<Namespace> path = TemplateUtils.relativePathWithMerge(namedElement, packageTemplate); Template template = UMLUtil.getStereotypeApplication(namedElement, Template.class); - TemplateKind templateKind = (template != null) ? - templateKind = template.getKind() : - TemplateKind.PASS_FORMAL; - + BindingHelper helper = (template != null) ? + template.getHelper() : null; + + /* if((templateKind == TemplateKind.ACCUMULATE) || (templateKind == TemplateKind.LATE_EVALUATION)) { // TODO: not very clean yet path = TemplateUtils.relativePathWithMerge(namedElement, copy.source); @@ -210,6 +217,7 @@ public class TemplateInstantiation { boundPackage = copy.target; // CreationUtils.getAndCreate // (sat.target, "accumulate"); } + */ if(path != null) { // register owning package template (template can be defined in @@ -248,19 +256,19 @@ public class TemplateInstantiation { // bound package. NamedElement existingMember = (NamedElement)copy.get(namedElement); + /* if((existingMember != null) && (templateKind != TemplateKind.ACCUMULATE)) { // element is already existing (and thus bound), nothing to do // additional check, whether the ACCUMULATE information is unset) // however: if the element is a package, existence is not sufficient // since it might have been created via getAndCreate above - /* - * if(namedElement instanceof Package) { - * bindPackage((Package)namedElement); - * } - */ + + //if(namedElement instanceof Package) { + // bindPackage((Package)namedElement); + //} return (T)existingMember; } - + */ if(existingMember == null) { FilterTemplate.getInstance().setActive(false); T copiedElement = copy.getCopy(namedElement); @@ -268,6 +276,7 @@ public class TemplateInstantiation { copy.setPackageTemplate(null, null); return copiedElement; } + return (T)existingMember; } 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 b41bb70d787..2023871a381 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 @@ -14,36 +14,16 @@ package org.eclipse.papyrus.qompass.designer.core.templates; -import org.eclipse.emf.common.util.BasicEList; -import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.util.EcoreUtil; -import org.eclipse.papyrus.C_Cpp.ConstInit; -import org.eclipse.papyrus.FCM.ActualChoice; +import org.eclipse.papyrus.FCM.BindingHelper; import org.eclipse.papyrus.FCM.Template; -import org.eclipse.papyrus.FCM.TemplateKind; -import org.eclipse.papyrus.qompass.designer.core.Messages; -import org.eclipse.papyrus.qompass.designer.core.PortUtils; -import org.eclipse.papyrus.qompass.designer.core.acceleo.AcceleoDriverWrapper; +import org.eclipse.papyrus.qompass.designer.core.extensions.BindingHelperExt; 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.TransformationContext; -import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; -import org.eclipse.uml2.uml.Behavior; import org.eclipse.uml2.uml.BehavioralFeature; -import org.eclipse.uml2.uml.Class; -import org.eclipse.uml2.uml.Classifier; import org.eclipse.uml2.uml.Element; -import org.eclipse.uml2.uml.EnumerationLiteral; -import org.eclipse.uml2.uml.Interface; -import org.eclipse.uml2.uml.NamedElement; import org.eclipse.uml2.uml.OpaqueBehavior; -import org.eclipse.uml2.uml.Operation; -import org.eclipse.uml2.uml.Parameter; -import org.eclipse.uml2.uml.Port; import org.eclipse.uml2.uml.TemplateBinding; -import org.eclipse.uml2.uml.TemplateParameterSubstitution; -import org.eclipse.uml2.uml.Type; import org.eclipse.uml2.uml.util.UMLUtil; /** @@ -90,244 +70,120 @@ 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; - } + // 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; } } - else { - Template template = UMLUtil.getStereotypeApplication((Element)sourceEObj, Template.class); - if((template != null)) { // && (!treatTemplateElement.containsKey(sourceEObj))) { - // treatTemplateElement.put(sourceEObj, true); - 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 { + 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; } - else { - Operation newOperation = instantiateOperation(actual, template, operation, boundClass); + 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(actual, template, (OpaqueBehavior)method); - newBehavior.setSpecification(newOperation); + instantiateBehavior(intfOperation, template, (OpaqueBehavior)method); + newBehavior.setSpecification(last); + // removalList.add(method); + copy.removeForCopy(method); // enable subsequent instantiations } } - return newOperation; } + // from a logical viewpoint, we need to copy parameters & name, but not the + // operation identity. + copy.put(operation, last); + return last; } - 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; + 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); } - 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; } + return newOperation; } } - } - } - return sourceEObj; - - } catch (TransformationException e) { - // throw runtime exception - throw new RuntimeException(String.format(Messages.TemplateInstantiationListener_TrafoException, e.getMessage())); - } - } - - public Operation instantiateOperation(Element actual, Template template, Operation operation, Class boundClass) { - try { - Operation newOperation = copy.getCopy(operation); - if(actual instanceof Operation) { - for(Parameter parameter : ((Operation)actual).getOwnedParameters()) { - Parameter newParam = EcoreUtil.copy(parameter); // copy parameter via EcoreUtil - newParam.setType(copy.getCopy(parameter.getType())); - newOperation.getOwnedParameters().add(newParam); - } - } - TransformationContext.classifier = newOperation.getClass_(); - if(actual instanceof Classifier) { - bindOperation(newOperation, (Classifier)actual); - } - String newName = AcceleoDriverWrapper.evaluate(operation.getName(), actual, args); - newOperation.setName(newName); - - return newOperation; - } catch (TransformationException e) { - // throw runtime exception - throw new RuntimeException(String.format(Messages.TemplateInstantiationListener_TrafoException, e.getMessage())); - } - } - - public OpaqueBehavior instantiateBehavior(Element actual, Template template, OpaqueBehavior opaqueBehavior) throws TransformationException { - OpaqueBehavior newBehavior = copy.getCopy(opaqueBehavior); - if(actual instanceof NamedElement) { - String newName = AcceleoDriverWrapper.evaluate(opaqueBehavior.getName(), actual, args); - newBehavior.setName(newName); - } - EList<String> bodyList = newBehavior.getBodies(); - for(int i = 0; i < bodyList.size(); i++) { - String body = bodyList.get(i); - TransformationContext.classifier = (Classifier)newBehavior.getOwner(); - // pass qualified operation name as template name. Used to identify script in case of an error - String newBody = AcceleoDriverWrapper.evaluate(body, newBehavior.getQualifiedName(), actual, args); - bodyList.set(i, newBody); - } - return newBehavior; - } - - - /** - * TODO: move into separate class - * - * @param element - * an element that is stereotyped with FCM::Template. The - * template parameter identified there is taken into account. If - * set to null, all actuals from the binding are returned. This - * is practical, since it implies that it is not necessary to - * specify the template parameter for the common case of a - * signature containing a single parameter. - * @return a list of actuals which, either for all parameters or the binding - * or a selection specified by the stereotype attribute - * templateParams (on element). - * @throws TransformationException - */ - public static EList<Classifier> getActuals(TemplateBinding binding, Element element) throws TransformationException { - Template template = UMLUtil.getStereotypeApplication(element, Template.class); - if(template != null) { - EList<Classifier> templateParams = template.getTemplateParams(); - EList<Classifier> actuals = new BasicEList<Classifier>(); - if(templateParams.size() == 0) { - for(TemplateParameterSubstitution substitution : binding.getParameterSubstitutions()) { - if(substitution.getActual() instanceof Classifier) { - actuals.add((Classifier)substitution.getActual()); + 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; + } } + */ } } - return actuals; } - return null; - } + return sourceEObj; - /** - * Useful (instead of first matching a certain type??) - * TODO: move into separate class - * - * @param element - * @param binding - * @return - * @throws TransformationException - */ - public static Classifier getFirstActualFromBinding(TemplateBinding binding, Element element) throws TransformationException { - EList<Classifier> actuals = getActuals(binding, element); - if((actuals != null) && (actuals.size() > 0) && (actuals.get(0) instanceof Classifier)) { - return (Classifier)actuals.get(0); - } - return null; + /* + } catch (TransformationException e) { + // throw runtime exception + throw new RuntimeException(String.format(Messages.TemplateInstantiationListener_TrafoException, e.getMessage())); } - - - /** - * Bind C++ const initializer - * - * @param operation - * @param actual - * @throws TransformationException - */ - public void bindOperation(Operation operation, Classifier actual) throws TransformationException { - // perform binding in case of C++ initializer - ConstInit cppConstInit = UMLUtil.getStereotypeApplication(operation, ConstInit.class); - if(cppConstInit != null) { - // TODO: specific to C++ - String init = cppConstInit.getInitialisation(); - String newInit = AcceleoDriverWrapper.bind(init, actual); - cppConstInit.setInitialisation(newInit); - } + */ } - /** - * @param actual - * the actual template parameter - * @param boundClass - * the bound class - * @param provides - * true, if the provided interface should be returned - * @return the provided or required interface of a port (of the passed - * boundClass) that is typed with the the actual. - */ - private static Interface getInterfaceFromPortTypedWithActual(Type actual, Class boundClass, boolean provided) { - for(Port port : PortUtils.getAllPorts(boundClass)) { - Interface provOrReqIntf; - if(provided) { - provOrReqIntf = PortUtils.getProvided(port); - } else { - provOrReqIntf = PortUtils.getRequired(port); - } - - if((port.getType() == actual) && (provOrReqIntf != null)) { - return provOrReqIntf; - } - } - return null; - } + /* private Type getPassedActual(Template template, Type actual, Class boundClass) { if(template.getActualChoice() == ActualChoice.INTERFACE_OF_PPORT) { return getInterfaceFromPortTypedWithActual(actual, boundClass, true); @@ -347,4 +203,5 @@ public class TemplateInstantiationListener implements CopyListener { } } } + */ } 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 410a5f35a37..46e9e609071 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 @@ -238,8 +238,7 @@ public class TemplateUtils { * parameter, or null if the 2nd parameter does not correspond to a * formal parameter of the binding. */ - public static Classifier getActualFromBinding( - TemplateBinding binding, Type formal) { + public static Classifier getActualFromBinding(TemplateBinding binding, Type formal) { for(TemplateParameterSubstitution substitution : binding.getParameterSubstitutions()) { ParameterableElement pe = substitution.getFormal().getParameteredElement(); if(pe == formal) { @@ -251,8 +250,7 @@ public class TemplateUtils { return null; } - public static Classifier getActualFromBinding( - TemplateBinding binding, String formalName) { + public static Classifier getActualFromBinding(TemplateBinding binding, String formalName) { for(TemplateParameterSubstitution substitution : binding.getParameterSubstitutions()) { ParameterableElement pe = substitution.getFormal().getParameteredElement(); Log.log(Status.INFO, Log.TEMPLATE_INSTANTIATION, String.format( @@ -266,6 +264,22 @@ public class TemplateUtils { } /** + * Get the first actual from the binding. + * + * @param binding the template binding + * @return the first actual. + */ + public static Classifier getFirstActualFromBinding(TemplateBinding binding) { + for(TemplateParameterSubstitution substitution : binding.getParameterSubstitutions()) { + ParameterableElement pe = substitution.getFormal().getParameteredElement(); + Log.log(Status.INFO, Log.TEMPLATE_INSTANTIATION, String.format( + Messages.TemplateUtils_InfoGetActualFrom, pe)); + return (Classifier)substitution.getActual(); + } + return null; + } + + /** * Return a sequence of namespaces for a given element, starting from the "bottom" * one, i.e. the one in which the element is contained. It will end before the * searchNS namespace is reached. Returns null, if the element is not contained diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/plugin.xml b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/plugin.xml index 19470e1d61b..896dae535c6 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/plugin.xml +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/plugin.xml @@ -129,6 +129,10 @@ <selection class="org.eclipse.core.resources.IResource"/> </wizard> </extension> + <extension id="LoopOperations" point="org.eclipse.papyrus.fcm.profile.fcmBindingHelper"> + <client class="org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers.LoopOperations" bindingHelperName="LoopOperations"> + </client> + </extension> <extension point="org.eclipse.help.toc"> <toc file="help/modellibs-core-examples.xml"/> <toc file="help/modellibs-core-library.xml"/> diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java index f2cbe552f92..369b1e2591a 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/Activator.java @@ -1,5 +1,6 @@ package org.eclipse.papyrus.qompass.modellibs.core; +import org.eclipse.papyrus.infra.core.log.LogHelper; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; @@ -14,6 +15,8 @@ public class Activator extends AbstractUIPlugin { // The shared instance private static Activator plugin; + public static LogHelper log; + /** * The constructor */ @@ -29,6 +32,9 @@ public class Activator extends AbstractUIPlugin { public void start(BundleContext context) throws Exception { super.start(context); plugin = this; + + // register the login helper + log = new LogHelper(plugin); } /* diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java new file mode 100644 index 00000000000..2f9874c8b1e --- /dev/null +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/bindinghelpers/LoopOperations.java @@ -0,0 +1,114 @@ +package org.eclipse.papyrus.qompass.modellibs.core.bindinghelpers; + +import org.eclipse.emf.common.util.BasicEList; +import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.papyrus.FCM.util.IBindingHelper; +import org.eclipse.papyrus.qompass.designer.core.acceleo.AcceleoDriverWrapper; +import org.eclipse.papyrus.qompass.designer.core.listeners.CopyListener; +import org.eclipse.papyrus.qompass.designer.core.templates.BindingUtils; +import org.eclipse.papyrus.qompass.designer.core.templates.TemplateUtils; +import org.eclipse.papyrus.qompass.designer.core.transformations.Copy; +import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationException; +import org.eclipse.papyrus.qompass.modellibs.core.Activator; +import org.eclipse.uml2.uml.Behavior; +import org.eclipse.uml2.uml.Class; +import org.eclipse.uml2.uml.Classifier; +import org.eclipse.uml2.uml.Element; +import org.eclipse.uml2.uml.EnumerationLiteral; +import org.eclipse.uml2.uml.Interface; +import org.eclipse.uml2.uml.OpaqueBehavior; +import org.eclipse.uml2.uml.Operation; +import org.eclipse.uml2.uml.TemplateBinding; +import org.eclipse.uml2.uml.Type; + +public class LoopOperations implements IBindingHelper, CopyListener { + + private TemplateBinding binding; + + @Override + public EObject copyEObject(Copy copy, EObject sourceEObj) { + + if(sourceEObj instanceof Operation) { + Operation operation = (Operation)sourceEObj; + + Classifier actual = TemplateUtils.getFirstActualFromBinding(binding); + Class boundClass = copy.getCopy(operation.getClass_()); + + if(!(actual instanceof Interface)) { + return sourceEObj; + } + Interface passedActualIntf = (Interface)actual; + Operation last = null; + EList<Element> removalList = new BasicEList<Element>(); + for(Operation intfOperation : passedActualIntf.getAllOperations()) { + for(Element removalElement : removalList) { + copy.removeForCopy(removalElement); // enable subsequent instantiations + } + removalList.clear(); + last = BindingUtils.instantiateOperation(copy, intfOperation, operation, boundClass); + removalList.add(operation); + for(Behavior method : operation.getMethods()) { + if(method instanceof OpaqueBehavior) { + try { + Behavior newBehavior = + BindingUtils.instantiateBehavior(copy, intfOperation, (OpaqueBehavior)method); + newBehavior.setSpecification(last); + } + catch (TransformationException e) { + Activator.log.error(e);; + } + // removalList.add(method); + copy.removeForCopy(method); // enable subsequent instantiations + } + } + } + // from a logical viewpoint, we need to copy parameters & name, but not the + // operation identity. + copy.put(operation, last); + return last; + /* + else { // not LOOP_OPERATIONS + Operation newOperation = instantiateOperation(actual, template, operation, boundClass); + for(Behavior method : operation.getMethods()) { + if(method instanceof OpaqueBehavior) { + Behavior newBehavior = + instantiateBehavior(actual, template, (OpaqueBehavior)method); + newBehavior.setSpecification(newOperation); + } + } + return newOperation; + */ + } + else if(sourceEObj instanceof EnumerationLiteral) { + EnumerationLiteral literal = (EnumerationLiteral)sourceEObj; + Classifier actual = TemplateUtils.getFirstActualFromBinding(binding); + // Type passedActual = getPassedActual(template, actual, boundClass); + Type passedActual = actual; + if(!(passedActual instanceof Interface)) { + return sourceEObj; + } + Interface passedActualIntf = (Interface)passedActual; + EnumerationLiteral newLiteral = null; + for(Operation intfOperation : passedActualIntf.getAllOperations()) { + copy.removeForCopy(literal); + newLiteral = copy.getCopy(literal); + try { + String newName = AcceleoDriverWrapper.evaluate(literal.getName(), intfOperation, null); + newLiteral.setName(newName); + } + catch (TransformationException e) { + Activator.log.error(e); + newLiteral.setName("none"); //$NON-NLS-1$ + } + } + return newLiteral; + } + return null; + } + + @Override + public void handleElement(TemplateBinding binding, Element object) { + this.binding = binding; + } +} diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java index 64a82385204..21bc29e0e2e 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/AnimServiceConfigurator.java @@ -17,7 +17,6 @@ package org.eclipse.papyrus.qompass.modellibs.core.iconfigurators; import org.eclipse.emf.common.util.EList; import org.eclipse.papyrus.qompass.designer.core.deployment.AllocUtils; import org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator; -import org.eclipse.papyrus.qompass.designer.core.transformations.ContainerContext; import org.eclipse.papyrus.qompass.designer.core.transformations.TransformationRTException; import org.eclipse.uml2.uml.InstanceSpecification; import org.eclipse.uml2.uml.NamedElement; @@ -51,9 +50,9 @@ public class AnimServiceConfigurator implements IInstanceConfigurator { * @param context * container context */ - public void configureInstance(InstanceSpecification instance, Property componentPart, ContainerContext context) + public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstance) { - EList<InstanceSpecification> nodes = AllocUtils.getAllNodesOrThreadsParent(context.smIS); + EList<InstanceSpecification> nodes = AllocUtils.getAllNodesOrThreadsParent(parentInstance); if (nodes.size() > 0) { InstanceSpecification node = nodes.get(0); NamedElement animService = node.getNearestPackage().getMember(eclipseAnimService); diff --git a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java index a342c2a9fbb..ca3a437adb0 100644 --- a/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java +++ b/extraplugins/qompass-designer/org.eclipse.papyrus.qompass.modellibs.core/src/org/eclipse/papyrus/qompass/modellibs/core/iconfigurators/CallEventConfigurator.java @@ -16,7 +16,6 @@ package org.eclipse.papyrus.qompass.modellibs.core.iconfigurators; import org.eclipse.papyrus.qompass.designer.core.deployment.DepPlanUtils; import org.eclipse.papyrus.qompass.designer.core.extensions.IInstanceConfigurator; -import org.eclipse.papyrus.qompass.designer.core.transformations.ContainerContext; import org.eclipse.uml2.uml.InstanceSpecification; import org.eclipse.uml2.uml.Property; @@ -47,9 +46,9 @@ public class CallEventConfigurator implements IInstanceConfigurator { * @param context * container context */ - public void configureInstance(InstanceSpecification instance, Property componentPart, ContainerContext context) + public void configureInstance(InstanceSpecification instance, Property componentPart, InstanceSpecification parentInstance) { - if(context != null) { + if(parentInstance != null) { // make sure that there is an enum par port // String literalName = "port_" + UMLTool.varName(context.port); //$NON-NLS-1$ |