import 'platform:/resource/uk.ac.le.cs.moment2.tests.exogenous/20080930_WADT_uml2rdbms_operation/metamodels/SimpleCD.ecore'; import 'platform:/resource/uk.ac.le.cs.moment2.tests.exogenous/20080930_WADT_uml2rdbms_operation/metamodels/SimpleDB.ecore'; transformation uml2rdbms ( uml : SimpleCD ; rdbms : SimpleDB) { // generation of schemas from packages eq PackageToSchema { lhs uml { p : Package { } }; lhs rdbms { }; rhs uml { p : Package { } }; rhs rdbms { s : Schema { } }; nac rdbms noSchema { s : Schema { } }; } // generation of tables from classes // we add a column and a key in the // generated table eq ClassToTable { lhs uml{ c : Class { package = p : Package {}, name = cn } }; lhs rdbms { s : Schema { } }; rhs uml{ c : Class { package = p : Package {}, name = cn } }; rhs rdbms { t : Table { schema = s : Schema { }, name = cn, columns = cl : Column { name = cn + "_tid", type = "NUMBER", nnv = true, unique = true }, key = k : Key { name = cn + "_pk", columns = cl : Column { } } } }; nac rdbms noTable { t : Table { name = cn } }; } // Generation of table columns from class attributes eq AttributeToColumn { lhs uml{ c : Class { name = cn, properties = a : Attribute { name = an, type = at } } }; lhs rdbms { t : Table { name = cn } }; rhs uml{ c : Class { name = cn, properties = a : Attribute { name = an, type = at } } }; rhs rdbms { t : Table { name = cn, columns = cl : Column { name = cn + "_" + an, type = if at == "INTEGER" then "NUMBER" else if at == "BOOLEAN" then "BOOLEAN" else "VARCHAR" endif endif } } }; nac rdbms noColumn { cl : Column { name = cn + "_" + an } }; } // Bidirectional associations are translated into // a table with two foreign keys. // In this transformation, we only consider bidirectional // associations where at least one of the association ends // has lower and upper bound = 1 // The generated table contains two foreign keys, two columns // and an empty key eq AssociationToTable { lhs uml{ ae1 : AssociationEnd { name = ae1name, owningClass = c1 : Class { name = c1name }, opposite = ae2 : AssociationEnd { name = ae2name, owningClass = c2 : Class { name = c2name } } } }; lhs rdbms { t1 : Table { name = c1name, key = k1 : Key { }, schema = s : Schema { } } t2 : Table { name = c2name, key = k2 : Key { } } }; rhs uml{ ae1 : AssociationEnd { name = ae1name, owningClass = c1 : Class { name = c1name }, opposite = ae2 : AssociationEnd { name = ae2name, owningClass = c2 : Class { name = c2name } } } }; rhs rdbms { t1 : Table { name = c1name, key = k1 : Key { }, schema = s : Schema { } } t2 : Table { name = c2name, key = k2 : Key { } } t : Table { // The name of the table is given by the names of the classes // and the names of the association ends. A single name // is generated independently of the order. name = if c1name < c2name then c1name + "_" + c2name else c2name + "_" + c1name endif, schema = s : Schema { }, fks = fk1 : ForeignKey { name = ae2name + "_fk", refersTo = k1 : Key { }, columns = cl2 : Column { } }, columns = cl1 : Column { name = ae1name, type = "NUMBER", owningTable = t : Table { } }, fks = fk2 : ForeignKey { name = ae1name + "_fk", refersTo = k2 : Key { }, columns = cl1 : Column { } }, columns = cl2 : Column { name = ae2name, type = "NUMBER", owningTable = t : Table { } }, columns = kColumn : Column { name = if c1name < c2name then c1name + "_" + c2name + "_tid" else c2name + "_" + c1name + "_tid" endif, type = "NUMBER", nnv = true, unique = true }, key = k : Key { name = if c1name < c2name then c1name + "_" + c2name + "_pk" else c2name + "_" + c1name + "_pk" endif, columns = kColumn : Column { } } } }; nac rdbms noColumn { t : Table { name = if c1name < c2name then c1name + "_" + c2name else c2name + "_" + c1name endif } }; } // This rule identifies the columns that are involved in the key // a table that has been generated for an association end, and // sets the properties not null value and unique for the columns // that are generated from the association. // Only those columns that are not null value and unique // are added. eq MultiplicityAssociationEndToForeignKeyProperties { lhs uml{ ae1 : AssociationEnd { lowerBound = lb, upperBound = ub, owningClass = c1 : Class { name = c1name }, type = c2 : Class { name = c2name } } }; lhs rdbms { fk1 : ForeignKey { refersTo = k1 : Key { owningTable = t1 : Table { name = c1name } }, columns = cl1 : Column { name = cl1Name } } }; rhs uml { c1 : Class { name = c1name } c2 : Class { name = c2name } }; rhs rdbms { fk1 : ForeignKey { refersTo = k1 : Key { owningTable = t1 : Table { name = c1name } }, columns = cl1 : Column { name = cl1Name, nnv = if (lb == 0) then false else true endif, unique = if (ub == 1) then true else false endif } } }; } }