ATLAS Transformation Language

Ken Webb 2010-04-19T20:08:14Z

The ATLAS Transformation Language (ATL) is "a model transformation language and toolkit".

A good introductory tutorial (Families2Persons) is available, as a presentation, and also described on a web page. To get a better idea of the ATL concepts, I've used Xholon to reimplement the model-to-model (m2m) transformation described in this ATL introductory tutorial. In this example, Xholon functions as a very lightweight modeling and transformation tool. Xholon is able to read the model described in the ATL tutorial (it reads the actual sample-Families.xmi file included in the tutorial). <pre> <?xml version="1.0" encoding="ISO-8859-1"?> <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"

   xmlns="platform:/resource/Xholon/src/org/primordion/user/app/AtlFamiliesToPersons/Families.ecore">
 <Family lastName="March">
   <father firstName="Jim"/>
   <mother firstName="Cindy"/>
   <sons firstName="Brandon"/>
   <daughters firstName="Brenda"/>
 </Family>
 <Family lastName="Sailor">
   <father firstName="Peter"/>
   <mother firstName="Jackie"/>
   <sons firstName="David"/>
   <sons firstName="Dylan"/>
   <daughters firstName="Kelly"/>
 </Family>

</xmi:XMI> </pre>

Once the model has been loaded, Xholon can run the following Xholon transformation script, which is written in Java. <pre> package org.primordion.user.app.AtlFamiliesToPersons;

import org.primordion.xholon.base.IXholon; import org.primordion.xholon.script.XholonScript; import org.primordion.xholon.service.IXholonService; import org.primordion.xholon.service.XholonHelperService;

/**

* This script performs a model-to-model (m2m) transformation,
* from a Families model to a Persons model.
* This script is based on Families2Persons.atl .
* The script should be pasted as a last child of a Families xmi:XMI node.
* <p>&lt;Families2Persons/></p>
*/

public class Families2Persons extends XholonScript {

 private StringBuffer personsSb = new StringBuffer();
 private StringBuffer malesSb = new StringBuffer();
 private StringBuffer femalesSb = new StringBuffer();
  
 /*
  * @see org.primordion.xholon.base.Xholon#postConfigure()
  */
 public void postConfigure() {
   personsSb.append("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
   personsSb.append("<xmi:XMI xmi:version=\"2.0\" xmlns:xmi=\"http://www.omg.org/XMI\" xmlns=\"Persons\">\n");
   // visit the subtree rooted by the Families xmi:XMI node
   getParentNode().visit(this);
   // males before females to agree with the ATL example
   personsSb.append(malesSb);
   personsSb.append(femalesSb);
   personsSb.append("</xmi:XMI>\n");
   System.out.println(personsSb); // m2t
   // paste the Persons model into the Xholon tree
   XholonHelperService xholonHelperService = (XholonHelperService)getService(IXholonService.XHSRV_XHOLON_HELPER);
   xholonHelperService.pasteAfter(getParentNode(), personsSb.toString());
   // remove this script from the Xholon tree
   this.removeChild();
 }
  
 /*
  * @see org.primordion.xholon.base.Xholon#visit(org.primordion.xholon.base.IXholon)
  */
 public boolean visit(IXholon visitee) {
   if (visitee.getXhc().hasAncestor("Member")) {
     boolean isFemale = isFemale(visitee);
     StringBuffer sb = isFemale ? sb = femalesSb : malesSb;
     sb.append("  <")
       .append(isFemale ? ruleMember2Female() : ruleMember2Male())
       .append(" fullName=\"")
       .append(((Member)visitee).getFirstName())
       .append(" ")
       .append(((Family)visitee.getParentNode()).getLastName())
       .append("\"/>\n");
   }
   return true;
 }
  
 /**
  * Is this family member a female?
  * Adapted from Families2Persons.atl .
  * @param familyMember father, mother, sons, or daughters
  * @return true (female) or false (male)
  */
 protected boolean isFemale(IXholon familyMember) {
   String familyMemberType = familyMember.getXhcName();
   if ("mother".equals(familyMemberType)) {
     return true;
   }
   else if ("daughters".equals(familyMemberType)) {
     return true;
   }
   else { // father or sons
     return false;
   }
 }
  
 /**
  * Adapted from a rule in Families2Persons.atl .
  * @return
  */
 protected String ruleMember2Male() {
   return "Male";
 }
  
 /**
  * Adapted from a rule in Families2Persons.atl .
  * @return
  */
 protected String ruleMember2Female() {
   return "Female";
 }

} </pre>

The result of running the Xholon transformation script, is the following XML which is exactly the same result in the ATL tutorial (sample-Persons.xmi). <pre> <?xml version="1.0" encoding="ISO-8859-1"?> <xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns="Persons">

 <Male fullName="Jim March"/>
 <Male fullName="Brandon March"/>
 <Male fullName="Peter Sailor"/>
 <Male fullName="David Sailor"/>
 <Male fullName="Dylan Sailor"/>
 <Female fullName="Cindy March"/>
 <Female fullName="Brenda March"/>
 <Female fullName="Jackie Sailor"/>
 <Female fullName="Kelly Sailor"/>

</xmi:XMI> </pre>

The following image shows the Xholon application running under Eclipse. The Xholon GUI shows the source (Families xmi:XMI subtree), as well as the generated target (Persons xmi:XMI) subtree. The image also shows the Xholon Console window which was opened on the Families xmi:XMI node, and was used to paste-in or apply the transformation script at runtime.

return to main page