• Aucun résultat trouvé

Conception et implantation en Kermeta

3.4 Système de types de Kermeta

4.2.3 Conception et implantation en Kermeta

Comme pour le développement de tout composant logiciel, la première étape de

dé-veloppement est la conception. Le fait d’utiliser un langage généraliste comme Kermeta

plutôt qu’un langage dédié à la transformation de modèle impose de porter un soin

par-ticulier à la conception. En effet, les langages dédiés à la transformation fournissent des

constructions et des structures adaptées à la définition de transformations de modèles

alors qu’une transformation écrite en Kermeta n’est qu’un programme orienté-objets

qui manipule des éléments de modèles.

Conception

La transformation CLS2RDB consiste à créer des tables pour chaque classe

mar-quée comme persistante dans le modèle source. Pour chaque attribut ou association

des classes persistantes, des colonnes ou clés étrangères sont ajoutées dans les tables

correspondantes. En pratique, cette transformation peut s’implanter par trois étapes

successives :

1. Création des tables. Création d’une table dans le modèle de sortie pour chaque

classe marquée persistante dans le modèle d’entrée.

2. Création des colonnes. Création d’un attribut pour chaque attribut ou référence

des classes persistantes dans le modèle d’entrée. Les colonnes correspondants aux

clés étrangères ne peuvent pas être créées lors de cette étape car toutes les clés

primaires des tables ne sont pas encore créées.

3. Mise-à-jour des clés étrangères. Dans cette troisième phase, les clés primaires de

toutes les tables sont à jour et il est donc possible de créer l’ensemble des colonnes

correspondant aux clés étrangères.

Entre les deux premières phases de la transformation il est nécessaire de garder

une information de traçabilité entre les éléments du modèle source et les éléments du

modèle résultat. En effet, afin d’ajouter les colonnes dans les tables appropriées lors de

la seconde phase, il est nécessaire de conserver un lien entre les classes persistantes et

les tables qui leur correspondent lors de la première phase. Ce besoin de stocker des

informations de traçabilité n’est pas propre à la transformation CLS2RDB mais est

observé de façon récurrente pour l’écriture de transformations de modèles.

En Kermeta plusieurs possibilités existent pour stocker les informations de

traça-bilité. La solution la plus simple est d’utiliser une structure de donnée disponible dans

le framework de Kermeta tel qu’une table de hachage par exemple. Cependant, étant

donné qu’il s’agit d’un problème récurrent il peut être avantageux de concevoir un

so-lution réutilisable sous la forme d’un framework de traçabilité. Le fait que Kermeta soit

un langage orienté-objets généraliste fait que son application à un domaine particulier

tel que l’écriture de transformations de modèles passe par la création de frameworks

spécialisés qui encapsulent les constructions du domaine.

La figure 4.17 présente l’implantation Kermeta d’une classe générique permettant

de stocker la correspondance entre deux types d’objets. L’utilisation des variables de

types génériques SRC et T GT permet de rendre la classe Trace réutilisable dans un

contexte de typage statique fort. L’implantation proposée est très simple et permet de

stocker des correspondances "un-un" unidirectionnelles entre deux ensembles d’objets.

Ce système de trace très simple est suffisant pour la transformation CLS2RDB mais

mériterait d’être enrichi en offrant par exemple la possibilité de stocker des traces

bi-directionnelles ou des correspondances mettant en jeu plus de deux objets.

La conception d’une transformation en Kermeta se fait comme la conception de

n’importe quel programme orienté-objets : conception de classes, création de

frame-works, utilisation de patrons de conceptions, etc. Une des particularités de Kermeta

pour la transformation de modèles est la possibilité d’encapsuler une partie du code

de la transformation dans le méta-modèle d’entrée et de sortie de la transformation.

Afin d’illustrer cette possibilité nous avons choisi d’intégrer au méta-modèle de base de

données l’étape 3 de la transformation qui consiste a créer les colonnes correspondant

aux clés étrangères. En effet, ce traitement est utile à la transformation CLS2RDB

Transformation de modèles 119

1 package trace ;

2 require kermeta

3 using kermeta :: utils

4

5 /* *

6 * This class represents a simple one to one

7 * unidirectional mapping

8 */

9 c l a s s Trace < SRC , TGT >

10 {

11 /* * Mapping between source and target objects */

12 reference src2tgt : Hashtable < SRC , TGT >

13

14 operation create () i s do

15 src2tgt := Hashtable < SRC , TGT >. new

16 end

17

18 /* * get a target element */

19 operation getTargetElem ( src : SRC ) : TGT i s do

20 r e s u l t := src2tgt . getValue ( src )

21 end

22

23 /* * Store a trace */

24 operation storeTrace ( src : SRC , tgt : TGT ) i s do

25 src2tgt . put ( src , tgt )

26 end

27 }

mais peut être également être utile à tout programme ou transformation qui utilise le

méta-modèle de base de données et qui crée des clés étrangères.

Pour ce qui est de la transformation elle-même et des traitements correspondant

aux étapes un et deux, nous avons choisi d’utiliser simplement une classe nommée

Class2RDBMS.

Implantation

La figure 4.18 présente le listing Kermeta contenant la classeClass2RDBMS, ses

pro-priétés et la méthodetransform qui constitue le point d’entrée de la transformation. La

première ligne du listing précise dans quel package est définie la classeClass2RDBMS.

Les lignes de 3 à 6 permettent d’importer les éléments qui sont utilisés dans la

trans-formation : le framework de base de Kermeta, le framework de trace que l’on a définit

précédemment et enfin les deux méta-modèles. On remarque que le méta-modèle de

classes est directement importé dans le format ECore (ligne 5) alors que pour le

méta-modèle de base de données, c’est la version Kermeta qui est utilisée (ligne 6).

La classe Class2RDBMS comporte deux références définies respectivement aux

lignes 13 et 15. La première, appeléeclass2table qui est utilisée pour stocker les

corres-pondances entre classes et tables entre les deux premières phases de la transformation

en utilisant la classe génériqueTrace définie précédemment. La seconde, nomméefkeys

permet de stocker l’ensemble des clés étrangères crées au cours de la transformation

afin de créer les colonnes correspondantes lors de la dernière phase. Pour représenter

cette collection, on a utilisé la classe génériqueCollection du framework de Kermeta.

L’opérationtransformest le point d’entrée de la transformation. On retrouve dans le

corps de cette méthode, un bloc d’initialisation suivi des trois phases de la

transforma-tion. Le bloc d’initialisation (lignes 18 à 22) permet de créer les structures de données

utilisées et d’initialiser le modèle résultat. La première phase de transformation assure

la création des tables correspondant aux classes marquées persistantes (ligne 23 à 29).

Pour chacune des classes marquées comme persistantes, une nouvelle table est créée,

ajoutée au modèle de sortie, et l’information de trace entre la classe et la nouvelle table

est stockée.

La seconde phase consiste à créer les colonnes correspondant à chaque table. Pour

cela on a défini une opération createColumns dont l’implantation est détaillée sur le

listing de la figure 4.19. Le code de cette opération est simple : il consiste tout d’abord

à ajouter l’ensemble des colonnes correspondant aux attributs (appel à l’opération

createColumnsForAttribute) de la classe puis à ajouter les colonnes correspondant aux

associations (appel à l’opérationcreateColumnsForAssociation).

L’opération createcolumnsForAttribute permet la création des colonnes

correspon-dant à un attribut. Trois cas doivent être pris en compte :

– Si le type de l’attribut est simple alors une seule colonne doit être créée.

– Si le type de l’attribut est une classe persistante alors une clé étrangère doit être

créée. Les colonnes correspondantes ne seront ajoutées dans la table que lors de

la troisième étape de la transformation.

Transformation de modèles 121

1 package Class2RDBMS ;

2

3 require kermeta // The kermerta standard library

4 require " trace . kmt " // The trace framework

5 require " ../ metamodels / ClassMM . ecore " // Input metamodel in ecore

6 require " ../ metamodels / RDBMSMM . kmt " // Output metamodel in kermeta

7

8 [...]

9

10 c l a s s Class2RDBMS

11 {

12 /* * The trace of the transformation */

13 reference class2table : Trace < Class , Table >

14 /* * Set of keys of the output model */

15 reference fkeys : Collection < FKey >

16

17 operation transform ( inModel : ClassModel ) : RDBMSModel i s do

18 // Initialize the trace

19 class2table := Trace < Class , Table >. new

20 class2table . create

21 fkeys := Set < FKey >. new

22 r e s u l t := RDBMSModel . new

23 // Create tables

24 getAllClasses ( inModel ). select { c | c. is_persistent }. each { c |

25 var table : Table i n i t Table . new

26 table . name := c. name

27 class2table . storeTrace (c , table )

28 r e s u l t. table . add ( table )

29 }

30 // Create columns

31 getAllClasses ( inModel ). select { c | c. is_persistent }. each { c |

32 createColumns ( class2table . getTargetElem ( c ) , c , " ")

33 }

34 // Create foreign keys

35 fkeys . each { k | k . createFKeyColumns }

36 end

37

38 [...]

39 }

1 operation createColumns ( table : Table , cls : Class , prefix : String ) i s

2 do

3 // add all attributes

4 getAllAttributes ( cls ). each { att |

5 createColumnsForAttribute ( table , att , prefix )

6 }

7 // add all associations

8 getAllAssociation ( cls ) . each { asso |

9 createColumnsForAssociation ( table , asso , prefix )

10 }

11 end

12

13 operation createColumnsForAttribute ( table : Table ,

14 att : Attribute ,

15 prefix : String ) i s

16 do

17 // The type is primitive : create a simple column

18 i f PrimitiveDataType . isInstance ( att . type ) then

19 var c : Column i n i t Column . new

20 c. name := prefix + att . name

21 c. type := att . type . name

22 table . cols . add (c)

23 i f att . is_primary then table . pkey . add ( c ) end

24 e l s e

25 var type : Class type ?= att . type

26 // The type is persitant

27 i f isPersistentClass ( type ) then

28 // Create a FKey

29 var fk : FKey i n i t FKey . new

30 fk . prefix := prefix + att . name

31 table . fkeys . add ( fk )

32 fk . references :=

33 class2table . getTargetElem ( getPersistentClass ( type ))

34 fkeys . add ( fk )

35 e l s e

36 // Recusively add all attrs and asso of the non persistent table

37 createColumns ( table , type , prefix + att . name )

38 end

39 end

40 end

Transformation de modèles 123

correspondant aux attributs de cette classe doit être créé. Cela est fait par un

appel récursif à l’opérationcreateColumns.

De la même manière, l’opération createcolumnsForAssociation permet la création des

colonnes correspondant à une association. Nous ne détaillons pas ici son implantation

car elle est très similaire à l’opérationcreatecolumnsForAttribute à l’exception près que

le type cible d’une association ne peut pas être un type simple.

1 c l a s s FKey

2 {

3 reference references : Table

4 reference cols : Column [1..*]

5

6 /* *

7 * prefix for the name of the columns

8 * used by the createFKeyColumns method

9 */

10 attribute prefix : String

11

12 /* *

13 * Create the FKey columns in the table

14 */

15 operation createFKeyColumns () i s do

16 var src_table : Table

17 src_table ?= container

18 // add columns

19 references . pkey . each { k |

20 var c : Column i n i t Column . new

21 c. name := prefix + k. name

22 c. type := k . type

23 s e l f. cols . add ( c)

24 src_table . cols . add ( c)

25 }

26 end

27 }

Fig.4.20 – Implantation de l’opérationcreateFKeyColumnsdans la classeFKeydu méta-modèle de

base de données.

Enfin, la figure 4.20 présente l’implantation de la troisième étape de la

transforma-tion, c’est-à-dire la création des colonnes correspondant à une clé étrangère. Comme

nous l’avons évoqué précédemment, l’opération permettant la création de ces colonnes

a été directement intégrée dans la classeFKey du méta-modèle de base de donnée. En

plus de l’opération createFKeyColumns nous avons ajouté un attribut prefix dans la

classeFKeyafin de stocker le préfixe à utiliser pour les noms des colonnes correspondant

à la clé étrangère.

4.2.4 Conclusion

Cette étude sur l’utilisation de Kermeta pour l’implantation de transformations de

modèles montre que, bien que le langage Kermeta ne soit pas dédié à la transformation

il présente des qualités intéressantes pour la réalisation de transfomations.

La première de ces qualités est de permettre la conception de code réutilisable dans

plusieurs transformations. Dans l’exemple de la transformation Class2RDBMS nous

avons, par exemple, intégré des opérations dans le méta-modèle de base de données. Ce

code, indispensable à la transformationClass2RDBMS, peut être réutilisé dans d’autre

transformations ou programmes qui manipulent des modèles de base de données. Nous

avons également créé un framework de traçabilité générique qui peut être réutilisé dans

toute application ayant besoin de garder une correspondance entre deux types d’objets.

Un autre avantage de Kermeta est la grande liberté de conception offerte par le

paradigme orienté-objets. Dans le contexte du workshop MTIP, Kermeta a permis

d’implanter aussi bien les transformations très structurelles comme la transformation

Class2RDBMS que les transformations plus algorithmiques comme la déterminisation

ou la minimisation d’automates. Les approches dédiées à la transformation ciblent

géné-ralement des type de transformation particuliers. Par exemple, les approches purement

déclaratives [LS05] ont de grandes qualités pour exprimer des transformations

structu-relles mais sont peu adaptées, bien que théoriquement utilisables, pour l’implantation

de transformation plus algorithmiques.