Comparing MDELite with ATL's Families to Persons Demo
The Atlas Transformation Language (ATL) is a first-generation MDE language for writing model-to-model (M2M) transformations. As such it is pioneering work against which future transformation languages should be compared. We invite readers to visit and digest the ATL example at:
http://wiki.eclipse.org/ATL/Tutorials_-_Create_a_simple_ATL_transformation
Here is an MDELite implementation of the Familes to Persons example. Here is the input database:
dbase(families,[family,member]).
table(family,[id,"lastName",fatherid,motherid]).
family(f1,'March',m1,m2).
family(f2,'Sailor',m5,m6).
table(member,[mid,"firstName",sonOf,daughterOf]).
member(m1,'Jim',null,null).
member(m2,'Cindy',null,null).
member(m3,'Brandon',f1,null).
member(m4,'Brenda',null,f1).
member(m5,'Peter',null,null).
member(m6,'Jackie',null,null).
member(m7,'David',f2,null).
member(m8,'Dylan',f2,null).
member(m9,'Kelly',null,f2).
and here is the translated database, the output of the Families2Persons transformation:
dbase(persons,[person,male,female]).
table(person,[id,"fullName"]).
table(male,[id,"fullName"]).
male(m1,'Jim March').
male(m5,'Peter Sailor').
male(m3,'Brandon March').
male(m7,'David Sailor').
male(m8,'Dylan Sailor').
table(female,[id,"fullName"]).
female(m2,'Cindy March').
female(m6,'Jackie Sailor').
female(m4,'Brenda March').
female(m9,'Kelly Sailor').
subtable(person,[male,female]).
In the following sections, I explain the Families2 Persons transformation program.
1. Initialization
The command-line input to the program is the input database (whose contents I listed above). Read the command line, extract the input file (database) name, and locate the output schema file:
// Step 1: standard marquee processing
Marquee1In_1Out mark = new Marquee1In_1Out(FamiliesM2M.class,
".families.pl", ".persons.pl", args);
String inputFileName = mark.getInputFileName();
String outputSchema = correct + "persons.schema.pl";
2. Read in Database Input Tables
Next, read in the database, and get the family and member tables:
// Step 2: read the families database and their tables
DB in = DB.read(inputFileName);
Table fam = in.getTableEH("family");
Table mem = in.getTableEH("member");
3. Read in Schema and Initialize Empty Output Tables
Read in the persons schema, create a new (and empty) database instance of this schema. Get the empty male and female tables in which we are to populate tuples:
// Step 3: create an empty persons database with empty tables
DBSchema outSchema = DBSchema.read(outputSchema);
DB inria = new DB(in.getName(), outSchema);
Table male = inria.getTableEH("male");
Table female = inria.getTableEH("female");
4. Perform the Model-to-Model Transformation
The join of the family and members table connects individuals with their family. Male tuples are fathers and sons of families; Female tuples are mothers and daughers of families. Four lines compute all male and female tuples:
// Step 4: fill in father tuples, mother tuples, son, then daughter
fam.join("fatherid", mem, "mid").forEach(t -> helper(male, t));
fam.join("motherid", mem, "mid").forEach(t -> helper(female, t));
fam.join("id", mem, "sonOf").forEach(t -> helper(male, t));
fam.join("id", mem, "daughterOf").forEach(t -> helper(female, t));
The above code, as in the ATL example, uses a helper function. It takes a table and a join tuple (which belongs to the cross-product of the member and family database) as input. From the tuple I extract the member's identifer, first name, and last name. The first and last names are concatenated, and to the input table, I add a tuple whose field values are member identifier, first+last name:
static void helper(Table tab, Tuple t) {
String id = t.get("member.mid");
String name = t.get("member.firstName") + " " + t.get("family.lastName");
tab.add(id, name);
}
An alternative -- and equally as general -- is to define correspondences between columns of tuples of dfferent schemas:
ColumnCorrespondence c = new ColumnCorrespondence()
.add("id",t->t.get("member.mid"))
.add("fullName",t->t.get("member.firstName") + " " + t.get("family.lastName"));
male.add(fam.join("fatherid", mem, "mid"),c);
female.add(fam.join("motherid", mem, "mid"),c);
male.add(fam.join("id", mem, "sonOf"),c);
female.add(fam.join("id", mem, "daughterOf"),c);
5. Print the Persons Database
Is all that remains to do:
// Step 5: print out database
inria.print();
Homework
Compare the above solution to that of ATL. I argue MDELite has the following advantages:
- MDE programmers don't have to learn yet another language to write M2M transformations,
- MDE programmers don't have to learn yet another language to write Model constraints,
- MDE programmers don't have to maintain a customized language -- the language of MDELite is Java 8, and Oracle does a better job of maintaining Java than any university-based research center could, and
- MDELite relies on fundamental concepts in computer science -- relational databases -- and reduces MDE complexity.