Model  2 Model Transformations in MOFScript


Model 2 Model Transformation can now be supported in MOFScript.

A Transformation may have any number of input or output parameters. For each out parameter, a new model instance is created according to the metamodel of the output metamodel.

Transformation Output Parameter

An output parameter represents the creation of some root model element. Which root element that should be created must be part of the parameter declaration:
In this way, the runtime knows which metamodel element to instantiate.

Creating new Objects - the 'new' operator

The new operator can be used when initialising object variables or assigning values.
The new operator creates a new instance of the specified type. A comma-separated list of parameters on the form <name=value> can be sent in the create call, which results in these properties being set on the created object. Further examples is given in the 'Create Ecore Example'

Adding Objects to Collections

Standard list operations can be used to add objects to the features owned by another object. Two basic variants of the add operation is provided by the MOFScript runtime: add and addOrg

Cloning an Object

Objects can be cloned by calling the operation clone(). Cloning can be used on any object structure and results in a deep copy of the object structure. This can be used for copying an input model, modifying it, and later storing it.

Storing a Model

Models are stored using the store("file name") operation on a model object. This operation can be executed on either output or input models.



Two examples are given. One taking a a UML model as input and producing a new UML model clone of the first one. The other, creating an ecore model from scratch.

UML2UML Transformation

texttransformation uml2uml (in uml:"http://www.eclipse.org/uml2/2.0.0/UML",
    out umlout:"http://www.eclipse.org/uml2/2.0.0/UML" (umlout.Model)) {

    uml.Model::main () {
      var outModel:umlout.Model;
      umlout.name = self.name + '_Cloned'
      ' In Model: ' self.name + ' Out Model: '  umlout.name '
      '           
      self.ownedMember->forEach(p:uml.Package) {
        '
        Package: ' p.name '
        '
        p.mapPackage (umlout)

      }           
      umlout.lookAtModel()
      umlout.store("myNewModel.uml")
    }   
   
    //
    //
    //
    uml.Package::mapPackage(outp:umlout.Package){           
      var newPackage:umlout.Package = new umlout.Package(name=self.name)
      outp.packagedElement.addOrg(newPackage)

      newPackage.name = newPackage.name + "_copy"
     
      self.ownedMember->forEach(p:uml.Package) {
        p.mapPackage(newPackage);
      }     
      self.ownedMember->forEach(c:uml.Class) {
        c.mapClass(newPackage)
      }           
    }
    //
    //
    //
    uml.Class::mapClass(outp:umlout.Package) {
      '
      Class to map: ' self.name '
      '
          outp.packagedElement.add(self)
          var added:umlout.NamedElement;
          added = outp.packagedElement.last()
          added.name = added.name + "_Clone"
    }
   
    umlout.Model::lookAtModel () {
      'Model ' self.name'
      '
      self.ownedMember->forEach(p:umlout.Package) {
        '
            Package: ' p.name ' size: ' p.ownedMember.size() '
        '
        p.ownedMember->forEach(c:umlout.Class) {
          '
                  Class: ' c.name
        }
      }
    }
}

Creating an Ecore Model

texttransformation m2mTest (out ec:"http://www.eclipse.org/emf/2002/Ecore" (ec.EPackage)) {
  module::main () {
    var theModel:ec.EPackage
   
    theModel = ec
    theModel.name = "Jons Model"
    var c1:ec.EClass = new ec.EClass(name="ole")
    theModel.eClassifiers.addOrg(c1)
       
    var class:ec.EClass = new ec.EClass(name="Factory")
    theModel.eClassifiers.addOrg(class)
   
    var carClass:ec.EClass = new ec.EClass(name="Car")
    theModel.eClassifiers.addOrg(carClass)   
   
    var carName:ec.EAttribute = new ec.EAttribute(name="name")
    carClass.eStructuralFeatures.addOrg(carName)
   
    var assoc:ec.EReference = new ec.EReference(name="cars", containment=true, upperBound=-1, eType=carClass)
    class.eStructuralFeatures.add(assoc)   
     
   
    println ("The Model: " + theModel.name)   
    ec.store("theModel.ecore")
  } 
}