Nous avons écrit des contrats de différents niveaux en Kermeta. Ici sont regroupés les contrats de niveau 2 à 5 : Niveau 2 : post pkey_is_in_the_column_of_its_table is result.table.forAll{t|t.pkey.forAll{pk|pk.container == t}} post columns_of_fkey_are_among_the_ones_of_its_table is result.table.forAll{t|t.fkeys.forAll{fk|fk.cols.forAll{c|t.cols.contains(c)}}} post table_number_equal_persistent_class_number is
// partie des règles 1 et 2
// Il y a autant de table que de classes persistante moins le nombre de // classes persistante ayant un parent persistant
result.table.size == inputModel.classifier
.select{cr|Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .size
post table_name_correspond_class_name is
// partie des règles 1 et 2
// Il y a au moins une classe persistante de même nom que chaque table, result.table.forAll{ t | inputModel.classifier
.select{cr | Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent} .exists{cs | cs.name == t.name}}
post class_name_correspond_table_name is
// partie des règles 1 et 2
// Il y a au moins une table de même nom que chaque classe persistante // sans parent persistant,
inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll{csp | result.table.exists{t |t.name == csp.name}}
post attribute_primitive_type is
// Création des colonnes correspondant aux attributs de type primitif inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | //pour toute classe persistante sans parent persistant
result.table.select{t|t.name == csp.name} //dans la table correspondante, .exists
{tn | csp.asType(Class).attrs
.select{at | PrimitiveDataType.isInstance(at.type)} // les attributs de type primitif
.forAll
{atp|tn.cols .select
{ctn|ctn.name==atp.name and ctn.type == atp.type.name }.size==1
}// ont 1 et 1 seule colonne correspondante dans la table }
153 Annexe A
post attribute_persistent_classes is
// Création des colonnes correspondant aux attributs dont le type est une // classe persistante transformée en table
inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant,
result.table.select{t|t.name == csp.name} //dans la table correspondante, .exists
{tn | csp.asType(Class).attrs
.select{at | Class.isInstance(at.type)}
// les attributs dont le type est une classe .select{atc|atc.type.asType(Class).is_persistent} //qui est persistante
.select{atcp | not atcp.type.asType(Class).allParents .exists{p | p.is_persistent}}
// mais sans parent persistant .forAll
{atcpwp|//(atcpwp est un attribut don’t le type est une classe //persistante sans parent persistant
atcpwp.type.asType(Class).attrs .forAll
{atcpta| //pour tous les attributs de ce type
if PrimitiveDataType.isInstance(atcpta.type)
//qui sont de type primitif
and atcpta.is_primary // et qui sont primaires then
tn.cols .select {ctn |
ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de cette // attribut + « _ » + le nom de l’attribut // primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut, }.size==1
//cette colonne est l’unique correpondante
else true end } } } }
post association_persistent_classes is
inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant, result.table
.select{t | t.name == csp.name} //dans la table correspondante, .exists
{tn | inputModel.association.select{ass|ass.src == csp} .select{atc | atc.dest.asType(Class).is_persistent} // qui est persistante
.select{atcp | not atcp.dest.asType(Class).allParents .exists{p | p.is_persistent}}
// mais sans parent persistant .forAll
{atcpwp | // (atcpwp is une association ciblant une classe // persistante sans parent persistant)
atcpwp.dest.attrs
.forAll //pour tous les attributs de cette classe cible {atcpta|
if PrimitiveDataType.isInstance(atcpta.type)
//qui sont de type primitif
and atcpta.is_primary // et qui sont primaires then
tn.cols .select {ctn |
ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de // cette association + « _ » + le nom de // l’attribut primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut }.size==1
//cette colonne est l’unique correpondante
else true end } } } }
155 Annexe A
Niveau 3 :
post attribute_primitive_type_and_primary_key is
// Ce contrat améliore le contrat « attribute_primitive_type » // Il considère la création des clés primaires (pkey)
inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | //pour toute classe persistante sans parent persistant result.table.select{t| t.name == csp.name}
//dans la table correspondante, .exists
{tn | csp.asType(Class).attrs
.select{at | PrimitiveDataType.isInstance(at.type)} // les attributs de type primitif
.forAll {atp| tn.cols
.select
{ctn|ctn.name==atp.name and ctn.type == atp.type.name }.size==1
//ont 1 et 1 seule col. correspondante dans la table
and
if atp.is_primary
then // si cette attribut est primaire
tn.pkey .contains
(tn.cols.select{ctn|ctn.name==atp.name
and ctn.type == atp.type.name }.one
//la table doit avoir cette colonne comme pkey ) else true end } } }
post attribute_persistent_classes_considering_fkey is
// Ce contrat améliore le contrat attribute_persistent_classes
// Ce contrat vérifie les colonnes d’une clé étrangère venant d’attributs inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant,
result.table.select{t|t.name == csp.name} //dans la table correspondante, .exists
{tn | csp.asType(Class).attrs
.select{at | Class.isInstance(at.type)}
// les attributs dont le type est une classe .select{atc|atc.type.asType(Class).is_persistent} //qui est persistante
.select{atcp | not atcp.type.asType(Class).allParents .exists{p | p.is_persistent}}
// mais sans parent persistant .forAll
{atcpwp| //(atcpwp est un attribut dont le type est une classe // persistante sans parent persistant)
atcpwp.type.asType(Class).attrs .forAll
{atcpta| //pour tous les attributs de ce type
if PrimitiveDataType.isInstance(atcpta.type)
//qui sont de type primitif
and atcpta.is_primary // et qui sont primaires then
tn.cols.select {ctn |
ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de cette // attribut + « _ » + le nom de l’attribut // primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut,
and tn.fkeys.exists{ftn|ftn.cols.contains(ctn)}
//et la colonne est fait partie des colonnes // d’une clé étrangère (FKey) de la table
}.size == 1
//cette colonne est l’unique correspondante
else true end
} } }
157 Annexe A
post association_persistent_classes_considering_fkeys is do
//Ce contrat améliore le contrat attribute_persistent_classes
//Ce contrat vérifie les colonnes d’une clé étrangère venant d’associations inputModel.classifier
.select{cr| Class.isInstance(cr)}.select{cs | cs.asType(Class).is_persistent} .select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant, result.table.select{t | t.name == csp.name}
//dans la table correspondante, .exists
{tn | inputModel.association.select{ass|ass.src == csp} // les associations de cette classe
.select{atc | atc.dest.asType(Class).is_persistent} // persistante
.select{atcp | not atcp.dest.asType(Class).allParents .exists{p|p.is_persistent}}
// mais sans parent persistant
.forAll // (atcpwp est une association ciblant une classe {atcpwp | // persistante sans parent persistant)
atcpwp.dest.attrs.forAll
{atcpta|//pour tous les attributs de cette classe cible
if PrimitiveDataType.isInstance(atcpta.type)
//qui sont de type primitif
and atcpta.is_primary // et qui sont primaires then
tn.cols.select{ctn |
ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de // cette association + « _ » + le nom de // l’attribut primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut
and tn.fkeys.exists
{fk|fk.references == result.table
.select{tr|tr.name==atcp.dest.name} .one
} //et la table a une clé étrangère qui //référence la table correspondant à la //classe persistante ciblée par l’association
}.size==1
else true end
} } }
Niveau 4 :
post association_persistent_classes_considering_fkeys_and_parent_child_assocs is // Ce contrat améliore association_persistent_classes_considering_fkeys
// Il considère les associations des classes de l’arbre d’héritage inputModel.classifier
.select{cr| Class.isInstance(cr)}.select{cs | cs.asType(Class).is_persistent} .select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant,
result.table.select{t|t.name == csp.name} //dans la table correspondante, .exists{tn | inputModel.association.select
{ass| ass.src==csp.asType(Class) // les associations de cette classe
or ass.src.allParents.contains(csp.asType(Class))//ou de ses filles or csp.asType(Class).allParents.contains(ass.src)
//ou de ses parents }.select{atc | atc.dest.asType(Class).is_persistent} // persistante
.select{atcp | not atcp.dest.asType(Class).allParents
.exists{p|p.is_persistent}} // mais sans parent persistant .forAll{atcpwp | // (atcpwp est une association ciblant une classe // persistante sans parent persistant)
atcpwp.dest.attrs.forAll
{atcpta| //pour tous les attributs de cette classe cible
if PrimitiveDataType.isInstance(atcpta.type)
//qui sont de type primitif
and atcpta.is_primary // et qui sont primaires then tn.cols.select
{ctn |
ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de // cette association + « _ » + le nom de // l’attribut primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut
and tn.fkeys.exists
{fk|fk.references == result.table
.select{tr|tr.name==atcp.dest.name}.one } // et la table a une clé étrangère qui // référence la table correspondant à la // classe persistante ciblée par
// l’association }.size==1
else true end
} } } }
159 Annexe A
Niveau 5 :
post attribute_primitive_type_and_child_attributes is
// Ce contrat améliore le contrat attribute_primitive_type
// Il vérifie les colonnes d’attributs primitifs en considérant l’héritage inputModel.classifier
.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll
{csp | // pour toute classe persistante sans parent persistant, result.table
.select{t | t.name == csp.name} //dans la table correspondante, .exists
{tn|var list_att: OrderedSet<Attribute> init OrderedSet<Attribute>.new
list_att.addAll(csp.asType(Class).attrs) inputModel.classifier
.select{cr|Class.isInstance(cr)} .select {crc|crc.asType(Class)
.allParents.contains(csp.asType(Class))} //pour tout enfant de la classe
.collect{cc|cc.asType(Class).attrs} //collecter ses attributs .each{atts|list_att.addAll(atts)}
//et ajouter les à sa liste d’attribut
list_att.select{at | PrimitiveDataType.isInstance(at.type)} .forAll // pour tout attribut de type primitif
{atp| tn.cols
.select {ctn| ctn.name==atp.name and ctn.type == atp.type.name
}.size==1
} il y a une seule colonne correspondante dans la table }
post attribute_persistent_classes_considering_fkey_and_child_attributes is
// Ce contrat améliore attribute_persistent_classes_considering_fkey
// Il vérifie les colonnes d’attributs non primitifs en considérant l’héritage inputModel.classifier.select{cr| Class.isInstance(cr)}
.select{cs | cs.asType(Class).is_persistent}
.select{csp | not csp.asType(Class).allParents.exists{p | p.is_persistent}} .forAll {csp | // pour toute classe persistante sans parent persistant,
result.table.select{t | t.name == csp.name} //dans la table correspondante, .exists
{tn| var list_att : OrderedSet<Attribute> init OrderedSet<Attribute>.new list_att.addAll(csp.asType(Class).attrs)
inputModel.classifier.select{cr|Class.isInstance(cr)} .select
{crc|crc.asType(Class).allParents.contains(csp.asType(Class))} //pour tout enfant de cette classe
.collect{cc|cc.asType(Class).attrs}//collecter ses attributs .each{atts|list_att.addAll(atts)}
//et les ajouter à sa liste d’attribut list_att.select{at | Class.isInstance(at.type)}
// ces attributs dont le type est une classe
.select{atc| atc.type.asType(Class).is_persistent} // persistante .select{atcp|not atcp.type.asType(Class).allParents
.exists{p|p.is_persistent}}//sans parent persistant .forAll{atcpwp | // (atcpwp est un attribut dont le type est //une classe persistante sans parent persistant atcpwp.type.asType(Class).attrs
.forAll {atcpta | //pour tous les attributs de ce type
if PrimitiveDataType.isInstance(atcpta.type)
//si c’est un attribut d’un type primitif
and atcpta.is_primary // et qui est primaire
then tn.cols.select
{ctn | ctn.name == atcpwp.name+"_"+atcpta.name // alors il y a une colonne du nom de cette // attribut + « _ » + le nom de l’attribut // primaire de type primitif
and ctn.type == atcpta.type.name
// et du type de ce dernier attribut,
and tn.fkeys.exists{ftn|ftn.cols.contains(ctn)}
//et la colonne est fait partie des colonnes // d’une clé étrangère (FKey) de la table
}.size == 1
//cette colonne est l’unique correspondante
else true end
} } }
161 Annexe A
A partir de ces contrats, nous obtenons quatre-vingt-quatre cas de test (6 modèles fois quatorze contrats) : CTcg1 : (MT7, o4, pkey_is_in_the_column_of_its_table) CTcg2 : (MT8, o4, pkey_is_in_the_column_of_its_table) CTcg3 : (MT9, o4, pkey_is_in_the_column_of_its_table) CTcg4 : (MT14, o4, pkey_is_in_the_column_of_its_table) CTcg5 : (MT15, o4, pkey_is_in_the_column_of_its_table) CTcg6 : (MT16, o4, pkey_is_in_the_column_of_its_table) CTcg7 : (MT7, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg8 : (MT8, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg9 : (MT9, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg10 : (MT14, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg11 : (MT15, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg12 : (MT16, o4, columns_of_fkey_are_among_the_ones_of_its_table) CTcg13 : (MT7, o4, table_number_equal_persistent_class_number) CTcg14 : (MT8, o4, table_number_equal_persistent_class_number) CTcg15 : (MT9, o4, table_number_equal_persistent_class_number) CTcg16 : (MT14, o4, table_number_equal_persistent_class_number) CTcg17 : (MT15, o4, table_number_equal_persistent_class_number) CTcg18 : (MT16, o4, table_number_equal_persistent_class_number) CTcg19 : (MT7, o4, table_name_correspond_class_nam) CTcg20 : (MT8, o4, table_name_correspond_class_nam) CTcg21 : (MT9, o4, table_name_correspond_class_nam) CTcg22 : (MT14, o4, table_name_correspond_class_nam) CTcg23 : (MT15, o4, table_name_correspond_class_nam) CTcg24 : (MT16, o4, table_name_correspond_class_nam) , etc.