diff options
Diffstat (limited to 'plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto')
-rw-r--r-- | plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto | 182 |
1 files changed, 126 insertions, 56 deletions
diff --git a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto index 3aaf0d42630..5e7f8f3c690 100644 --- a/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto +++ b/plugins/uml/alf/org.eclipse.papyrus.uml.alf.to.fuml/transformation/AlfExpression2UML.qvto @@ -423,28 +423,78 @@ helper InvocationExpression::InvocationExpression_mapTarget(inout graph : Expres if self.isImplicit then { graph.nodes += action := new DestroyObjectAction(self.feature.expression.type.toUml().oclAsType(Class)); } else { - var element := self.referent.toUml(); - switch { - case(element.oclIsKindOf(Operation)) { - graph.nodes += action := new CallOperationAction(element.oclAsType(Operation)); - graph.resultSource := action.returnPin(); - } - case(element.oclIsKindOf(Signal)) { - graph.nodes += action := new SendSignalAction(element.oclAsType(Signal)); - } - case(element.oclIsKindOf(Behavior)) { - graph.nodes += action := new CallBehaviorAction(element.oclAsType(Behavior)); - graph.resultSource := action.returnPin(); - } - case(element.oclIsKindOf(Property)) { - graph.nodes += action := new ReadLinkAction(element.oclAsType(Property)); - graph.resultSource := action._'output'->at(1); - } + var element := + if self.isCollectionFunctionInvocation() then + // Optimize the invocation of a (not in-place) collection function by calling + // the corresponding sequence function directly. + self.sequenceFunction() + else + self.referent.toUml() + endif; + + switch { + case(element = null) { + graph.nodes += action := new ValueSpecificationAction(new LiteralNull()); + graph.resultSource := action.output->at(1); + } + case(element.oclIsKindOf(Operation)) { + graph.nodes += action := new CallOperationAction(element.oclAsType(Operation)); + graph.resultSource := action.returnPin(); + } + case(element.oclIsKindOf(Signal)) { + graph.nodes += action := new SendSignalAction(element.oclAsType(Signal)); + } + case(element.oclIsKindOf(Behavior)) { + graph.nodes += action := new CallBehaviorAction(element.oclAsType(Behavior)); + graph.resultSource := action.returnPin(); + } + case(element.oclIsKindOf(Property)) { + graph.nodes += action := new ReadLinkAction(element.oclAsType(Property)); + graph.resultSource := action.output->at(1); + }; }; } endif; return action; } +helper InvocationExpression::isCollectionFunctionInvocation() : Boolean { + var referent := self.referent; + var template := referent.template(); + return referent.isTemplateBinding() and + template.namespace() <> null and + template.namespace().equals(self.collectionFunctionsPackage()); +} + +query InvocationExpression::sequenceFunction() : Behavior { + var behavior : Behavior := null; + var name := self.referent.template().name(); + + if name <> "clear" then { + var sequenceFunctionName := + switch { + case(name = "add") "Including"; + case(name = "addAll") "Union"; + case(name = "addAt") "IncludeAt"; + case(name = "addAllAt") "IncludeAllAt"; + case(name = "remove") "Excluding"; + case(name = "removeAll") "Difference"; + case(name = "removeOne") "ExcludingOne"; + case(name = "removeAt") "ExcludeAt"; + case(name = "replace") "Replacing"; + case(name = "replaceOne") "ReplacingOne"; + case(name = "replaceAt") "ReplacingAt"; + else name.firstToUpper(); + }; + behavior := self.sequenceFunction(sequenceFunctionName); + } endif; + + return behavior; +} + +helper InvocationExpression::collectionFunctionsPackage() : ElementReference { + return self.resolveInLibrary("CollectionFunctions")![isPackage()]; +} + helper InvocationExpression::mapTuple(inout graph : ExpressionGraph, action : Action) : ActivityGraph { return self.tuple.map toActivityGraph(graph, action, null, null); } @@ -606,32 +656,36 @@ mapping _Tuple::toActivityGraph(inout graph : ExpressionGraph, action : Action, // Add collection and bit string conversions, if required. self.mapConversions(inputGraph, expressionType, input.isCollectionConversion, input.isBitStringConversion); - var inputPin := action.input->at(i); - edges += new ObjectFlow(inputGraph.resultSource, inputPin); - - // Check for an index on the argument name (as opposed to the argument expression itself). - var index := input.index; - if index <> null or invocation.oclIsKindOf(LinkOperationExpression) and inputPin.isOrdered then { - var indexSource : ActivityNode; - if index = null then { - inputGraph.nodes += var valueAction ::= new ValueSpecificationAction(self.literalUnlimited()); - indexSource := valueAction.result; - } else { - var indexGraph := index.map toActivityGraph(); - indexGraph.addTo(result); - indexSource := indexGraph.resultSource; - if self.isIntegerType(index.type) then { - inputGraph.nodes += var callAction ::= new CallBehaviorAction(self.integerFunction("ToUnlimitedNatural")); - inputGraph.edges += new ObjectFlow(inputGraph.resultSource, callAction.argument->at(1)); - indexSource := callAction.result->at(1); + // NOTE: For the mapping of CollectionFunctions::clear, the action will be a value specification action, + // with no input. + if i <= action.input->size() then { + var inputPin := action.input->at(i); + edges += new ObjectFlow(inputGraph.resultSource, inputPin); + + // Check for an index on the argument name (as opposed to the argument expression itself). + var index := input.index; + if index <> null or invocation.oclIsKindOf(LinkOperationExpression) and inputPin.isOrdered then { + var indexSource : ActivityNode; + if index = null then { + inputGraph.nodes += var valueAction ::= new ValueSpecificationAction(self.literalUnlimited()); + indexSource := valueAction.result; + } else { + var indexGraph := index.map toActivityGraph(); + indexGraph.addTo(result); + indexSource := indexGraph.resultSource; + if self.isIntegerType(index.type) then { + inputGraph.nodes += var callAction ::= new CallBehaviorAction(self.integerFunction("ToUnlimitedNatural")); + inputGraph.edges += new ObjectFlow(inputGraph.resultSource, callAction.argument->at(1)); + indexSource := callAction.result->at(1); + } endif; } endif; - } endif; - // NOTE: This presumes that the "insertAt" or "destroyAt" pin comes directly after - // the value pin in the list of input pins. - i := i + 1; - inputGraph.edges += new ObjectFlow(indexSource, action.input->at(i)); + // NOTE: This presumes that the "insertAt" or "destroyAt" pin comes directly after + // the value pin in the list of input pins. + i := i + 1; + inputGraph.edges += new ObjectFlow(indexSource, action.input->at(i)); + } endif; } endif; - + inputGraph.addTo(subgraph); i := i + 1; }; @@ -648,17 +702,22 @@ mapping _Tuple::toActivityGraph(inout graph : ExpressionGraph, action : Action, outputParameters->forEach(parameter) { var output := outputs![name = parameter.name()]; if output <> null and not output.expression.isNull() then { - var outputGraph := object ExpressionGraph{}; + var outputGraph := object ExpressionGraph{ + resultSource := action.output->at(i) + }; + var lhs := output.leftHandSide; var lhsGraph := lhs.map toActivityGraph(objectSourceMap->get(output.name), indexSourceMap->get(output.name), -1); lhsGraph.addTo(outputGraph); - - // Skip the return pin. The return parameter never has an output argument. - outputGraph.resultSource := action.output->at(i); - if outputGraph.resultSource = returnPin then { + + if invocation.isCollectionFunctionInvocation() then { + graph.resultSource := lhsGraph.resultSource; + } else if outputGraph.resultSource = returnPin then { + // Unless this is the mapping of an in-place collection function invocation, skip a return pin. + // The return value is not normally given through a tuple argument. i := i + 1; outputGraph.resultSource := action.output->at(i); - } endif; + } endif endif; // Add collection and bit string conversion, if required. self.mapConversions(outputGraph, parameter.type(), output.isCollectionConversion, output.isBitStringConversion); @@ -1387,15 +1446,20 @@ mapping CastExpression::toActivityGraph() : ExpressionGraph if type = null or operandType <> null and operandType.conformsTo(self.type) and - // The following condition is to treat up-casting of - // naturals to unlimited naturals as a real conversion, - // because naturals are represented as integers. - not(self.isNaturalType(operandType) and self.isUnlimitedNaturalType(type)) or + // The following condition is to treat up-casting of + // naturals to unlimited naturals as a real conversion, + // because naturals are represented as integers. + not(self.isNaturalType(operandType) and self.isUnlimitedNaturalType(type)) or // The following condition is an optimization to avoid // generating an expansion region when the operand is known // to be null. - self.operand.isNull() then { + self.operand.isNull() or + + // TODO: Implement casts to template parameters. + type.isTemplateParameter() + + then { // Up-cast, no conversion is necessary. resultSource := operandGraph.resultSource; @@ -1670,10 +1734,16 @@ mapping ClassificationExpression::toActivityGraph() : ExpressionGraph var operandGraph := self.operand.map toActivityGraph(); operandGraph.addTo(result); - var classifier := self.referent.toUml().oclAsType(Classifier); - nodes += var action ::= new ReadIsClassifiedObjectAction(classifier, self.isDirect, self.booleanType().toType()); - edges += new ObjectFlow(operandGraph.resultSource, action._'object'); - resultSource := action.result; + if self.referent.isTemplateParameter() then { + // TODO: Implement classification check for template parameters. + nodes += var valueAction ::= new ValueSpecificationAction(self.literalBoolean(true)); + resultSource := valueAction.result; + } else { + var classifier := self.referent.toUml().oclAsType(Classifier); + nodes += var action ::= new ReadIsClassifiedObjectAction(classifier, self.isDirect, self.booleanType().toType()); + edges += new ObjectFlow(operandGraph.resultSource, action._'object'); + resultSource := action.result; + } endif; } // Equality Expressions |