blob: 554c38b64bd52609fa5bb3371aec9438e7c964a4 [file] [log] [blame]
pre {
"Running ETL".println();
var db : new DB!Database;
}
post {
// Store traceability links in custom model
var trace : new Trace!Trace;
for (t in transTrace.transformations) {
var link : new Trace!TraceLink;
link.sources.add(t.source);
link.targets = t.targets;
link.description = "Transformed by " + t.getRule().name;
trace.links.add(link);
}
}
// Transforms a class into a table and
// a primary key column
rule Class2Table
transform c : OO!Class
to t : DB!Table, pk : DB!Column {
t.name = c.name;
t.database = db;
// Fill the details of the primary key
// of the table
pk.name = t.primaryKeyName();
pk.type = "INT";
t.columns.add(pk);
t.primaryKeys.add(pk);
// If the class extends some other class
// create a foreign key pointing towards
// the primary key of the parent class
if (c.`extends`.isDefined()){
var fk : new DB!ForeignKey;
var childFkCol : new DB!Column;
var parentFkCol : DB!Column;
var parentTable : DB!Table;
parentTable ::= c.`extends`;
parentFkCol = parentTable.primaryKeys.first();
childFkCol.name = parentFkCol.name;
childFkCol.type = "INT";
childFkCol.table = t;
fk.database = db;
fk.parent = parentFkCol;
fk.child = childFkCol;
fk.name = c.name + "Extends" + c.`extends`.name;
}
}
// Transforms a single-valued attribute
// to a column
rule SingleValuedAttribute2Column
transform a : OO!Attribute
to c : DB!Column {
guard : not a.isMany
c.name = a.name;
c.table ::= a.owner;
c.type = a.type.name.toDbType();
}
// Transforms a multi-valued attribute
// to a table where its values are stored
// and a foreign key
rule MultiValuedAttribute2Table
transform a : OO!Attribute
to t : DB!Table, pkCol : DB!Column, valueCol : DB!Column,
fkCol : DB!Column, fk : DB!ForeignKey {
guard : a.isMany
// The table that stores the values
// has an "id" column and a "value" column
t.name = a.valuesTableName();
t.database = db;
pkCol.name = "id";
pkCol.table = t;
pkCol.type = "INT";
valueCol.name = "value";
valueCol.table = t;
valueCol.type = a.type.name.toDbType();
// Another column is added into the table
// to link with the "id" column of the
// values table
fkCol.name = a.name + "Id";
fkCol.table ::= a.owner;
fkCol.type = "INT";
// The foreign key that connects
// the two columns is defined
fk.parent = pkCol;
fk.child = fkCol;
fk.database = db;
}
// Transforms a referecne into a foreign key
rule Reference2ForeignKey
transform r : OO!Reference
to fk : DB!ForeignKey, fkCol : DB!Column {
fkCol.table ::= r.type;
fkCol.name = r.name + "Id";
fkCol.type = "INT";
fk.database = db;
fk.parent = r.owner.equivalent().primaryKeys.first();
fk.child = fkCol;
fk.name = r.name;
}
operation DB!Table primaryKeyName() : String {
return self.name.firstToLowerCase() + "Id";
}
operation OO!Attribute valuesTableName() : String {
return self.owner.name + "_" + self.name.firstToUpperCase() + "Values";
}
operation Any toDbType() : String {
var mapping : OO2DB!TypeMapping;
mapping = OO2DB!TypeMapping.allInstances().
select(tm|tm.source = self).first;
if (not mapping.isDefined()){
("Cannot find DB type for OO type " + self +
". Setting the default.").println();
return OO2DB!TypeMap.allInstances().first().`default`.target;
}
else {
return mapping.target;
}
}