Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
ATL Language Troubleshooter
< To: ATL
Contents
Trouble Cause Solution(s)
ATL Virtual Machine Troubles
- Trouble: NativeOperation public static org.atl.engine.vm.nativelib.ASMNumber org.atl.engine.vm.nativelib.ASMInteger.operatorMinus(org.atl.engine.vm.StackFrame,org.atl.engine.vm.nativelib.ASMInteger,org.atl.engine.vm.nativelib.ASMNumber)
- Cause: You use negative integer to compare
- e.g. if self.upper = -1 ...
- Solutions: Use (0-x) operation
- e.g. if self.upper = (0-1) ... or change your comparaison if it is possible: e.g. if self.upper < 0 ...
ATL Called Rules Troubles
- Trouble: ERROR: could not find operation including on Module having supertypes: [OclAny]) on a called rule
- Cause: Your called rule doesn't return the good type (problably any)
- Solution: Add a return type on your called rule by adding the do clause
- e.g.
- Cause: Your called rule doesn't return the good type (problably any)
rule myCalledRule() { to out : XML!Element -- ... do { out; } }
ATL matched, called and lazy rules: differences
- a matched rule is a declarative rule whose "from" pattern is automatically matched by the ATL engine
- a lazy Rule is a declarative rule which is explicitely called
- a called Rule is a imperative rule which is explicitely called
As ATL prefered coding style is declarative, you should better use matched and lazy rule.
How to call lazy rules ?
Let a simple lazy rule:
lazy rule getCross { from i: ecore!EObject to rel: metamodel!Relationship ( ) }
We can call it from a matched rule as follows:
rule Example { from s : ecore!EObject to t : metamodel!Node ( name <- s.toString(), edges <- thisModule.getCross(s) }
If we want to call lazy rule multiple times:
rule Example { from s : ecore!EObject to t : metamodel!Node ( name <- s.toString(), edges <- ecore!EClass.allInstancesFrom('yourmodel')->collect(e | thisModule.getCross(e)) }
UML2 Profiles
N.B.: The following text concerns Eclipse 3.1 / UML2 v1.1. It does not apply to Eclipse 3.2 / UML2 v2.0 or later.
Eclipse UML2 Profiles and Stereotypes cannot be applied directly via ATL, but must use the native Java methods of the UML2 plug-in. See also atl_discussion message 1202.
The reason is that UML2 Profiles contain a small Ecore meta-model, with an EClass for each Stereotype defined. When a Profile is applied, this small meta-model is added to the set of available meta-models. Whenever a Stereotype is applied, an EAnnotation "appliedStereotypes" is created (or modified) and an instance of the EClass for that stereotype is added to the contents of the EAnnotation.
This can create problems with ATL, since ATL rules are intended to be confluent (i.e. execution order of rules does not matter). A Profile application basically changes the meta-model at run-time. Any Stereotype application can only happen after the Profile has been applied. Things become even more complex when unapplying Profiles/Stereotypes.
N.B.: The following text concerns UML2 v.2.1 and running ATL programmaticaly
Loading UML2 models by the instruction
ASMModel in = this.emfMh.loadModel("IN", uml2Metamodel, URI.createURI(relPath2Input));
URI.createURI(relPath2Input)
URI.createFileURI(new java.io.File(relPath2Input).getAbsolutePath())
resolves the problem.
Rule inheritance
NOTE: do not forget to put the --@atlcompiler atl2006 at the beginning of your ATL file to use this ATL 2006 specific language feature
Rule inheritance is a new feature of ATL 2006 release. It is a compiler-feature, not an Virtual Machine one. It means that it is only a static translation.
There is two keywords introduced by rules inheritance: abstract and extends. They can be used like this:
abstract rule A { from [fromA] using [usingA] to [toA] do [doA] } rule B extends A { from [fromB] using [usingB] to [toB] do [doB] } rule C extends B { from [fromC] using [usingC] to [toC] do [doC] }
When the ATL2006 compiler compiles (sic) this transformation, it is the same as if you gave this as input:
rule B { from [fromB] using [usingB] to [toA.bindings union toB.bindings] do [doB] } rule C { from [fromC] using [usingC] to [toA.bindings union toB.bindings union toC.bindings] do [doC] }
However, there are some limitations and constraints. First, ATL2006 does not support multiple inheritances and it is not planned to be implemented. Constraints are the following:
- sub rules (e.g. B or C) input pattern (i.e. the from part) has to match a subset of its super rule. For instance, if you match particular class in a super rule, you have to have a more restrictive filter or match a sub class.
- input pattern variables names have to be the same in super and sub rules.
- output pattern variables names have to be the same in super and sub rules for output pattern you want the union.
Here is a complete example to illustrate. It is a KM3-copier, i.e. every model element from the source model is copied as-is to the target model:
-- @atlcompiler atl2006 module Copy; create OUT : MM from IN : MM; rule CopyDataType extends CopyClassifier { from s : MM!DataType to t : MM!DataType } rule CopyEnumeration extends CopyClassifier { from s : MM!Enumeration to t : MM!Enumeration ( literals <- s.literals ) } rule CopyParameter extends CopyTypedElement { from s : MM!Parameter to t : MM!Parameter } rule CopyReference extends CopyStructuralFeature { from s : MM!Reference to t : MM!Reference ( isContainer <- s.isContainer, opposite <- s.opposite ) } rule CopyTypedElement extends CopyModelElement { from s : MM!TypedElement to t : MM!TypedElement ( lower <- s.lower, upper <- s.upper, isOrdered <- s.isOrdered, isUnique <- s.isUnique, type <- s.type ) } rule CopyOperation extends CopyTypedElement { from s : MM!Operation to t : MM!Operation ( parameters <- s.parameters ) } rule CopyAttribute extends CopyStructuralFeature { from s : MM!Attribute to t : MM!Attribute } rule CopyEnumLiteral extends CopyModelElement { from s : MM!EnumLiteral to t : MM!EnumLiteral } rule CopyPackage extends CopyModelElement { from s : MM!Package to t : MM!Package ( contents <- s.contents ) } rule CopyClass extends CopyClassifier { from s : MM!Class to t : MM!Class ( isAbstract <- s.isAbstract, supertypes <- s.supertypes, structuralFeatures <- s.structuralFeatures, operations <- s.operations ) } rule CopyClassifier extends CopyModelElement { from s : MM!Classifier to t : MM!Classifier } abstract rule CopyModelElement extends CopyLocatedElement { from s : MM!ModelElement to t : MM!ModelElement ( name <- s.name ) } rule CopyMetamodel extends CopyLocatedElement { from s : MM!Metamodel to t : MM!Metamodel ( contents <- s.contents ) } abstract rule CopyLocatedElement { from s : MM!LocatedElement to t : MM!LocatedElement ( location <- s.location ) } rule CopyStructuralFeature extends CopyTypedElement { from s : MM!StructuralFeature to t : MM!StructuralFeature ( subsetOf <- s.subsetOf, derivedFrom <- s.derivedFrom ) }