Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
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.qvto182
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

Back to the top