transformation HelloWorld1(); main() { log('Hello world'); }
modeltype ECORE 'strict' uses 'http://www.eclipse.org/emf/2002/Ecore'; transformation HelloWorld2(out o : ECORE); main() { object EPackage { name := 'World'; eClassifiers += object EClass { name := 'Alice'; }; eClassifiers += object EClass { name := 'Bob'; }; }; }
Note
Hereinafter, I will not describe the language syntax in too much detail. You can get to know him in the specification or in this presentation . In the next article, we will consider QVTo in more detail.
modeltype ECORE 'strict' uses 'http://www.eclipse.org/emf/2002/Ecore'; transformation HelloWorld3(in i : ECORE, out o : ECORE); main() { i.rootObjects()[EPackage]->toEPackage(); } mapping EPackage::toEPackage() : EPackage { name := 'Hello' + self.name; eClassifiers := self.eClassifiers->toEDataType(); } mapping EClassifier::toEDataType() : EDataType { name := 'Hello' + self.name; instanceClassName := 'some.ns.' + self.name + 'Class'; serializable := false; }
-- @nsURI Ecore = http://www.eclipse.org/emf/2002/Ecore module HelloWorld3; create OUT : Ecore from IN : Ecore; rule toEPackage { from package : Ecore!EPackage to newPackage : Ecore!EPackage ( name <- 'Hello' + package.name, eClassifiers <- package.eClassifiers ) } rule toEDataType { from classifier : Ecore!EClassifier to dataType : Ecore!EDataType ( name <- 'Hello' + classifier.name, instanceClassName <- 'some.ns.' + classifier.name + 'Class', serializable <- false ) }
Note
INRIA was attached to the creation of ATL and, frankly, it can be seen in the syntax :) From their Caml, I also have two visions. Excellent office, but there is a feeling that their languages are different from other languages as well as French is different from English. The letters seem to be similar, but something is wrong.
Note
Sometimes it happens that you change something in the transformation, but it works as before. In this case, delete the asm-file and, if it does not automatically re-create, then there is something wrong with the conversion. For example, I used the drop statement in the conversion, which is only supported in the new version of the ATL compiler, which must be explicitly included with a special directive. However, I did not receive any errors, and the asm file simply was not silently regenerated.
<?xml version="1.0"?> <project name="HelloWorldATL"> <target name="HelloWorld3"> <!-- Loading metamodels --> <atl.loadModel name="Ecore" metamodel="MOF" nsURI="http://www.eclipse.org/emf/2002/Ecore" /> <!-- Loading models --> <atl.loadModel name="IN" metamodel="Ecore" path="output/MyModel2.xmi" /> <!-- Transformation --> <atl.launch path="HelloWorld3.atl"> <inmodel name="IN" model="IN" /> <outmodel name="OUT" model="OUT" metamodel="Ecore" /> </atl.launch> <!-- Saving models --> <atl.saveModel model="OUT" path="output/MyModel3.xmi" /> </target> </project>
-- @atlcompiler atl2010 -- @nsURI Ecore = http://www.eclipse.org/emf/2002/Ecore module HelloWorld4; create OUT : Ecore refining IN : Ecore; rule sayHello { from s : Ecore!ENamedElement (s.name <> 'Bob') to t : Ecore!ENamedElement ( name <- 'Hello' + s.name ) } rule killBob { from s : Ecore!ENamedElement (s.name = 'Bob') to drop }
<?xml version="1.0"?> <project name="HelloWorldATL"> <target name="HelloWorld4"> <!-- Loading metamodels --> <atl.loadModel name="Ecore" metamodel="MOF" nsURI="http://www.eclipse.org/emf/2002/Ecore" /> <!-- Loading models --> <atl.loadModel name="IN" metamodel="Ecore" path="output/MyModel2.xmi" /> <!-- Transformation --> <atl.launch path="HelloWorld4.atl" refining="true"> <inoutmodel name="IN" model="IN" /> </atl.launch> <!-- Saving models --> <atl.saveModel model="IN" path="output/MyModel4.xmi" /> </target> </project>
-- @nsURI Ecore = http://www.eclipse.org/emf/2002/Ecore module HelloWorld5; create OUT : Ecore from IN : Ecore; rule SayHelloToAlice { from classifier : Ecore!EClassifier ( classifier.name = 'Alice' ) to datatype : Ecore!EDataType ( name <- 'Hello' + classifier.name ) } rule SayHelloToBob { from classifier : Ecore!EClassifier ( classifier.name = 'Bob' ) to datatype : Ecore!EDataType ( name <- 'Hello' + classifier.name ) }
<?xml version="1.0"?> <project name="HelloWorldATL"> <target name="ATLCopy"> <!-- Loading metamodels --> <atl.loadModel name="ATL" metamodel="MOF" nsURI="platform:/plugin/org.eclipse.m2m.atl.common/org/eclipse/m2m/atl/common/resources/ATL.ecore" /> <!-- Loading models --> <atl.loadModel name="IN" metamodel="ATL" path="HelloWorld5.atl"> <injector name="ATL" /> </atl.loadModel> <!-- Saving models --> <atl.saveModel model="IN" path="output/HelloWorld5.atl.xmi" /> </target> </project>
<?xml version="1.0" encoding="ISO-8859-1"?> <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:atl="http://www.eclipse.org/gmt/2005/ATL" xmlns:ocl="http://www.eclipse.org/gmt/2005/OCL"> <atl:Module location="3:1-26:2" name="HelloWorld5"> <commentsBefore>-- @nsURI Ecore = http://www.eclipse.org/emf/2002/Ecore</commentsBefore> <inModels location="4:25-4:35" name="IN" metamodel="/2"/> <outModels location="4:8-4:19" name="OUT" metamodel="/1"/> <elements xsi:type="atl:MatchedRule" location="6:1-15:2" name="SayHelloToAlice"> <outPattern location="11:2-14:4"> <elements xsi:type="atl:SimpleOutPatternElement" location="12:3-14:4" varName="datatype"> <type xsi:type="ocl:OclModelElement" location="12:14-12:29" name="EDataType" model="/4"/> <bindings location="13:4-13:37" propertyName="name"> <value xsi:type="ocl:OperatorCallExp" location="13:12-13:37" operationName="+"> <source xsi:type="ocl:StringExp" location="13:12-13:19" stringSymbol="Hello"/> <arguments xsi:type="ocl:NavigationOrAttributeCallExp" location="13:22-13:37" name="name"> <source xsi:type="ocl:VariableExp" location="13:22-13:32" referredVariable="/0/@elements.0/@inPattern/@elements.0"/> </arguments> </value> </bindings> </elements> </outPattern> <inPattern location="7:2-10:4"> <elements xsi:type="atl:SimpleInPatternElement" location="8:3-8:33" varName="classifier" variableExp="/0/@elements.0/@inPattern/@filter/@source/@source /0/@elements.0/@outPattern/@elements.0/@bindings.0/@value/@arguments.0/@source"> <type xsi:type="ocl:OclModelElement" location="8:16-8:33" name="EClassifier" model="/3"/> </elements> <filter xsi:type="ocl:OperatorCallExp" location="9:4-9:29" operationName="="> <source xsi:type="ocl:NavigationOrAttributeCallExp" location="9:4-9:19" name="name"> <source xsi:type="ocl:VariableExp" location="9:4-9:14" referredVariable="/0/@elements.0/@inPattern/@elements.0"/> </source> <arguments xsi:type="ocl:StringExp" location="9:22-9:29" stringSymbol="Alice"/> </filter> </inPattern> </elements> <elements xsi:type="atl:MatchedRule" location="17:1-26:2" name="SayHelloToBob"> <outPattern location="22:2-25:4"> <elements xsi:type="atl:SimpleOutPatternElement" location="23:3-25:4" varName="datatype"> <type xsi:type="ocl:OclModelElement" location="23:14-23:29" name="EDataType" model="/6"/> <bindings location="24:4-24:37" propertyName="name"> <value xsi:type="ocl:OperatorCallExp" location="24:12-24:37" operationName="+"> <source xsi:type="ocl:StringExp" location="24:12-24:19" stringSymbol="Hello"/> <arguments xsi:type="ocl:NavigationOrAttributeCallExp" location="24:22-24:37" name="name"> <source xsi:type="ocl:VariableExp" location="24:22-24:32" referredVariable="/0/@elements.1/@inPattern/@elements.0"/> </arguments> </value> </bindings> </elements> </outPattern> <inPattern location="18:2-21:4"> <elements xsi:type="atl:SimpleInPatternElement" location="19:3-19:33" varName="classifier" variableExp="/0/@elements.1/@inPattern/@filter/@source/@source /0/@elements.1/@outPattern/@elements.0/@bindings.0/@value/@arguments.0/@source"> <type xsi:type="ocl:OclModelElement" location="19:16-19:33" name="EClassifier" model="/5"/> </elements> <filter xsi:type="ocl:OperatorCallExp" location="20:4-20:27" operationName="="> <source xsi:type="ocl:NavigationOrAttributeCallExp" location="20:4-20:19" name="name"> <source xsi:type="ocl:VariableExp" location="20:4-20:14" referredVariable="/0/@elements.1/@inPattern/@elements.0"/> </source> <arguments xsi:type="ocl:StringExp" location="20:22-20:27" stringSymbol="Bob"/> </filter> </inPattern> </elements> </atl:Module> <ocl:OclModel location="4:14-4:19" name="Ecore" model="/0/@outModels.0"/> <ocl:OclModel location="4:30-4:35" name="Ecore" model="/0/@inModels.0"/> <ocl:OclModel location="8:16-8:21" name="Ecore" elements="/0/@elements.0/@inPattern/@elements.0/@type"/> <ocl:OclModel location="12:14-12:19" name="Ecore" elements="/0/@elements.0/@outPattern/@elements.0/@type"/> <ocl:OclModel location="19:16-19:21" name="Ecore" elements="/0/@elements.1/@inPattern/@elements.0/@type"/> <ocl:OclModel location="23:14-23:19" name="Ecore" elements="/0/@elements.1/@outPattern/@elements.0/@type"/> </xmi:XMI>
Note
Unfortunately, because of one ATL bug in the ANT script, you have to write some dubious path to ATL.ecore. And the resulting XMI file cannot be opened in the normal tree model editor, because the namespaces www.eclipse.org/gmt/2005/ATL and www.eclipse.org/gmt/2005/OCL are not registered in Eclipse. This can be corrected, but we will not be distracted, for the purposes of the article this is not essential. The main thing that you see is that the ATL transform can be represented as a model.
-- @nsURI Ecore = http://www.eclipse.org/emf/2002/Ecore -- @path ATL = platform:/plugin/org.eclipse.m2m.atl.common/org/eclipse/m2m/atl/common/resources/ATL.ecore module GenerateHelloWorld; create OUT : ATL from IN : Ecore; rule EPackageToModule { from package : Ecore!EPackage to _module : ATL!Module ( name <- 'HelloWorld5', inModels <- thisModule.createEcoreModel('IN'), outModels <- thisModule.createEcoreModel('OUT'), elements <- package.eClassifiers ) } rule EClassifierToRule { from classifier : Ecore!EClassifier to _rule : ATL!MatchedRule ( name <- 'SayHelloTo' + classifier.name, inPattern <- _in, outPattern <- _out ), -- InPattern _in : ATL!InPattern ( elements <- inElement, filter <- inFilter ), inElement : ATL!SimpleInPatternElement ( varName <- 'classifier', type <- thisModule.createEcoreModelElement('EClassifier') ), inFilter : ATL!"OCL::OperatorCallExp" ( operationName <- '=', source <- thisModule.createAttributeCallExp(inElement, 'name'), arguments <- thisModule.createStringExp(classifier.name) ), -- OutPattern _out : ATL!OutPattern ( elements <- outElement ), outElement : ATL!SimpleOutPatternElement ( varName <- 'datatype', type <- thisModule.createEcoreModelElement('EDataType'), bindings <- nameBinding ), nameBinding : ATL!Binding ( propertyName <- 'name', value <- helloPrefixOperatorExp ), helloPrefixOperatorExp : ATL!"OCL::OperatorCallExp" ( operationName <- '+', source <- thisModule.createStringExp('Hello'), arguments <- thisModule.createAttributeCallExp(inElement, 'name') ) } lazy rule createEcoreModel { from name : String to model : ATL!OclModel ( name <- name, metamodel <- ecoreMM ), ecoreMM : ATL!OclModel ( name <- 'Ecore' ) } lazy rule createEcoreModelElement { from name : String to element : ATL!"OCL::OclModelElement" ( model <- model, name <- name ), model : ATL!OclModel ( name <- 'Ecore' ) } lazy rule createAttributeCallExp { from var : ATL!SimpleInPatternElement, name : String to expr : ATL!"OCL::NavigationOrAttributeCallExp" ( name <- name, source <- variableExp ), variableExp : ATL!"OCL::VariableExp" ( referredVariable <- var ) } lazy rule createStringExp { from str : String to expr : ATL!"OCL::StringExp" ( stringSymbol <- str ) }
<?xml version="1.0"?> <project name="HelloWorldATL"> <target name="GenerateHelloWorld"> <!-- Loading metamodels --> <atl.loadModel name="Ecore" metamodel="MOF" nsURI="http://www.eclipse.org/emf/2002/Ecore" /> <atl.loadModel name="ATL" metamodel="MOF" nsURI="platform:/plugin/org.eclipse.m2m.atl.common/org/eclipse/m2m/atl/common/resources/ATL.ecore" /> <!-- Loading models --> <atl.loadModel name="IN" metamodel="Ecore" path="output/MyModel2.xmi" /> <!-- Transformation --> <atl.launch path="GenerateHelloWorld.atl"> <inmodel name="IN" model="IN" /> <outmodel name="OUT" model="OUT" metamodel="ATL" /> </atl.launch> <!-- Saving models --> <atl.saveModel model="OUT" path="output/HelloWorld5.atl"> <extractor name="ATL" /> </atl.saveModel> </target> </project>
Note
To be honest, you need to get used to the diagram editor. For example, if you fail to change the order of the rules in the Sequential Unit, then you can change it in the tree-like model editor.
package HelloWorldHenshin; import org.eclipse.emf.henshin.interpreter.EGraph; import org.eclipse.emf.henshin.interpreter.Engine; import org.eclipse.emf.henshin.interpreter.UnitApplication; import org.eclipse.emf.henshin.interpreter.impl.EGraphImpl; import org.eclipse.emf.henshin.interpreter.impl.EngineImpl; import org.eclipse.emf.henshin.interpreter.impl.UnitApplicationImpl; import org.eclipse.emf.henshin.model.Module; import org.eclipse.emf.henshin.model.resource.HenshinResourceSet; public class Main { public static void main(String[] args) { HenshinResourceSet resourceSet = new HenshinResourceSet("model"); Module module = resourceSet.getModule("HelloWorld.henshin", false); EGraph graph = new EGraphImpl(resourceSet.getResource("MyModel2.xmi")); Engine engine = new EngineImpl(); UnitApplication app = new UnitApplicationImpl(engine); app.setEGraph(graph); app.setUnit(module.getUnit("main")); if (!app.execute(null)) { throw new RuntimeException("Execution error"); } resourceSet.saveEObject(graph.getRoots().get(0), "MyModel3.xmi"); } }
Source: https://habr.com/ru/post/273449/
All Articles