Model-to-Model (M2M)

Home > Model Transformation > Model-to-Model (M2M)

OOMEGA ATL provides an OOMEGA-specific virtual machine for the ATLAS Transformation Language (ATL). You can use that third-party model-to-model transformation engine and its language ATL to transform models that were designed with OOMEGA.

We do not provide detailed documentation for the product ATL as there are already good sources available in the internet. Please consult the respective websites. However we will explain here how to use ATL on top of OOMEGA.

Please notice first of all that there is a working example. The Model-to-Model demo project (org.oomega.demo.m2m.atl) demonstrates model transformation with ATL. The chapter Demo Projects explains how to setup and run this demo project. The source code of that project is probably a good starting point for you.

Start ATL transformations with Ant

First of all it is important to set the atl.launcher property so that the OOMEGA-specific virtual machine will be used when executing ATL scripts.

<property name="atl.launcher" value="OOMEGA-specific VM" />

Instead of using the standard ATL tasks (<atl.loadModel>, <atl.launch>, <atl.saveModel>) you are required to use the pendants from OOMEGA, namely:

  • <oomega-atl.loadModel>
  • <oomega-atl.launch>
  • <oomega-atl.saveModel>

Their main purpose is to set classpaths correctly. In particular you can set the classpath attribute within these Ant tasks which is needed to inject the required metamodel classes. Apart from that, OOMEGA-specific Ant tasks are identical to their ATL counterparts.

oomega-atl.loadModel

The loadModel task is needed to load metamodels and models. Here's an example how to load a metamodel from a SDF file.

<oomega-atl.loadModel name="families-and-persons-mm" metamodel="%OOMEGA" path="models/oomega/metamodel-Families-Persons.sdf" />

  • The name attribute is set in order to reference the metamodel at a later stage.
  • The metamodel attribute references the built-in meta-metamodel, i.e. %OOMEGA.
  • The path attribute points to the resource containing the metamodel definition. In that case we are using a FileEOC to load the metamodel from a SDF file.

You could also replace the path attribute with the uri attribute when you want to load the metamodel from a remote repository.

<oomega-atl.loadModel name="families-and-persons-mm" metamodel="%OOMEGA" uri="oomega-network://host:port" />

Now you must load an instance of your metamodel, i.e. a model. This can be done as follows:

<oomega-atl.loadModel name="families-m" metamodel="families-and-persons-mm" path="models/oomega/sample-Families.sdf" classpath="lib/oomega-atl-demo-core.jar" />

  • The name attribute is set in order to reference the model at a later stage.
  • The metamodel attribute references the previously loaded metamodel, i.e. families-and-persons-mm.
  • The path attribute points to the resource containing the model. In that case we are using a FileEOC to load the model from a SDF file. Again you could replace the path attribute by the uri attribute for loading the model from a remote repository (see above).
  • The classpath attribute is finally needed to inject the required metamodel classes into the classloader.

oomega-atl.launch

The launch task is used to start the actual model-to-model transformation. Here's an example:

<oomega-atl.launch path="atl/Families2Persons.asm" classpath="lib/oomega-atl-demo-core.jar">
    <inmodel name="Families" model="families-and-persons-mm" />
    <inmodel name="Persons" model="families-and-persons-mm" />
    <inmodel name="IN" model="families-m" />
    <outmodel name="OUT" model="persons-m" metamodel="families-and-persons-mm" />
</oomega-atl.launch>
  • The path attribute of the launch task points to the compiled ATL script. Templates should have been compiled automatically by the standard ATL Eclipse plug-in as soon as you have saved your ATL script.
  • The classpath attribute is needed again to inject the required metamodel classes into the classloader.

Then you need to provide e.g. three <inmodel> tags and one <outmodel> tag.

  • <inmodel name="Families" model="families-and-persons-mm" /> injects the Families metamodel into the launcher. That metamodel is contained within the previously loaded metamodel families-and-persons-mm.
  • <inmodel name="Persons" model="families-and-persons-mm" /> injects the Persons metamodel into the launcher. That metamodel is contained within the previously loaded metamodel families-and-persons-mm.
  • <inmodel name="IN" model="families-m" /> injects an instance of the Families metamodel into the launcher. That model has been loaded previously with the name families-m.
  • <outmodel name="OUT" model="persons-m" metamodel="families-and-persons-mm" /> finally defines the output model persons-m.

<inmodel> and <outmodel> tags always define the attributes name and model.

  • The name attribute defines a name that will be used within ATL scripts.
  • The model attributes points either to a previously loaded metamodel/model or to a model that should be saved (see below).
  • The metamodel attribute is only needed within the <outmodel> tag and points to the metamodel definition of the model that should be produced by the transformation engine.

oomega-atl.saveModel

The saveModel task is needed to store an output model into a model repository.

<oomega-atl.saveModel model="persons-m" path="models/oomega/sample-Persons.sdf" classpath="lib/oomega-atl-demo-core.jar" />

  • The model attribute contains the name of the model that should be saved. It references the name previously defined within the <outmodel> tag.
  • The path attribute points to the resource where the model should be stored. In that case we are using a FileEOC to store the model in a SDF file. Again you could replace the path attribute by the uri attribute for storing the model in a remote repository (see above).
  • The classpath attribute is finally needed to inject the required metamodel classes into the classloader.

Ant script of the org.oomega.demo.m2m.atl demo project

Here's the whole Ant script of the org.oomega.demo.m2m.atl demo project. The contents have been already discussed in previous paragraphs.

Please notice that the Ant script must be run in the same JRE as the workspace as described in chapter Model-to-Model Demo (org.oomega.demo.m2m.atl). This is - by the way - not a specific requirement of the OOMEGA-specific VM but rather a general requirement of the ATL implementation.

<project name="build.oomega" default="build-oomega">

    <property name="atl.launcher" value="OOMEGA-specific VM" />

    <target name="build-oomega">
        <oomega-atl.loadModel name="families-and-persons-mm" metamodel="%OOMEGA" path="models/oomega/metamodel-Families-Persons.sdf" />
        <oomega-atl.loadModel name="families-m" metamodel="families-and-persons-mm" path="models/oomega/sample-Families.sdf" classpath="lib/oomega-atl-demo-core.jar" />

        <oomega-atl.launch path="atl/Families2Persons.asm" classpath="lib/oomega-atl-demo-core.jar">
            <inmodel name="Families" model="families-and-persons-mm" />
            <inmodel name="Persons" model="families-and-persons-mm" />
            <inmodel name="IN" model="families-m" />
            <outmodel name="OUT" model="persons-m" metamodel="families-and-persons-mm" />
        </oomega-atl.launch>

        <oomega-atl.saveModel model="persons-m" path="models/oomega/sample-Persons.sdf" classpath="lib/oomega-atl-demo-core.jar" />
    </target>

</project>

Code ATL templates

There's nothing special to say about coding ATL templates. You can write them in the well-known and standardized way. Please consult third-party documentation about the ATL product itself to become familiar with that model transformation language.

Here's a simple example of an ATL script that is part of our demo project. In fact this is a standard example provided by the ATL team.

module Families2Persons;
create OUT : Persons from IN : Families;

helper context Families!Member def: familyName : String =
    if not self.familyFather.oclIsUndefined() then
        self.familyFather.lastName
    else
        if not self.familyMother.oclIsUndefined() then
            self.familyMother.lastName
        else
            if not self.familySon.oclIsUndefined() then
                self.familySon.lastName
            else
                self.familyDaughter.lastName
            endif
        endif
    endif;

helper context Families!Member def: isFemale() : Boolean =
    if not self.familyMother.oclIsUndefined() then
        true
    else
        if not self.familyDaughter.oclIsUndefined() then
            true
        else
            false
        endif
    endif;
	
rule Member2Male {
    from
        s : Families!Member (not s.isFemale())
    to
        t : Persons!Male (
            fullName <- s.firstName + ' ' + s.familyName	
        )
}

rule Member2Female {
    from
        s : Families!Member (s.isFemale())
    to
        t : Persons!Female (
            fullName <- s.firstName + ' ' + s.familyName	
        )
}
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.