Mise en oeuvre de Eclipse GMF avec Acceleo

Acceleo 1.1 est officiellement sorti, cette version apporte la compatibilité avec Eclipse 3.2 et par conséquent le très prometteur projet GMF. Nous allons voir dans ce tutorial comment Acceleo peut être utilisé de concert avec GMF afin d'offrir une plateforme dirigée par les modèles dédiée aux "Domain Specific Models". Grâce à cette approche il devient possible de réaliser des modeleurs spécifiques à un besoin précis puis de générer le code ou le texte correspondant à ce modèle via Acceleo. Dans cet article nous nous attachons à la réalisation d'un générateur de slides XHTML à partir d'une carte mentale.

Article lu   fois.

L'auteur

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Installation et préparation

I.1. Présentation

Cet article présente l'utilisation du générateur de code Acceleo de concert avec les modeleurs spécifiques. On peut considérer qu'il s'agit de la suite logique du tutorial de démarage du projet GMF qui traite de la création d'un modeleur spécifique: un outil de "MindMapping". Ce modeleur permet la formalisation d'idées que l'on peut mettre en relation.

Site officiel d'Acceleo

Dans cet article nous détaillerons la réalisation d'un générateur de code pour cet outil de "MindMapping". Il s'agit de générer des slides (en XHTML) à partir d'une carte mentale, les idées principales représentent autant de slides et les idées annexes des points à aborder au sein d'un slide.

Image non disponible
Modèle Mindmap GMF + résultat avec Acceleo

Vous pouvez d'ors et déjà consulter un exemple de slides générés via le lien suivant. De plus tous les projets réalisés le long de cet article sont disponibles en téléchargement.

Exemple de slides générés

I.2. Installation d'Acceleo

Il faut dans un premier temps installer Acceleo, ses dépendances ainsi que GMF qui permet l'utilisation de modeleurs spécifiques. Un bundle est disponible sur le site d'Acceleo, ce dernier (bundle-emf-uml2-gmf-acceleo-1.1.0) permet l'installation simultanée d'Acceleo et de GMF.

Page de téléchargement d'Acceleo 1.1

Pour de plus amples informations concernant l'installation d'Acceleo, reportez-vous aux instructions disponibles sur le site d'Acceleo.

Site officiel Acceleo

Si tout s'est bien déroulé une nouvelle perspective "Acceleo" doit être disponible au sein d'Eclipse.

Image non disponible
Sélection de la perspective Acceleo

I.3. Installation du modeleur de MindMap

Cet article repose également sur un plugin produit grace au projet GMF. Ce plugin contient le modeleur de MindMap.

Le projet GMF propose un article détaillant la réalisation de ce modeleur, vous êtes invité à le consulter si vous souhaitez réaliser votre propre modeleur spécifique. Nous montrons ici comment l'exploiter. Nous avons compilé ce plugin réalisé à partir du même méta-modèle, téléchargez-le puis décompressez-le dans le répertoire d'installation de votre Eclipse.

Si le plugin n'est pas pris en compte dans votre environnement Eclipse, il peut être nécessaire de fermer Eclipse, d'effacer les répertoires contenus dans "configuration" de votre installation Eclipse puis de re-démarrer ce dernier.

Outil de MindMapping pour Eclipse

Tutorial GMF :réalisation d'un outil de MindMapping

Vous pouvez vérifier la bonne installation de l'outil MindMapping en créant un projet vide puis en choisissant "File", "New" puis "Other" dans Eclipse. Une catégorie "Obeo Domain Specific Modeler" doit être disponible, elle permet la création d'une nouvelle carte mentale.

Image non disponible
Acceleo Domain Specific Modeler : MindMapping

II. Mise en place de l'environnement

II.1. Présentation

Le principe général de la génération est le suivant : Acceleo utilise un template pour générer du code (ou texte) à partir d'un modèle. Ici le modèle est la carte mentale, le code généré est un ensemble de fichiers XHTML qui correspondent aux slides que l'on obtient.

Image non disponible
Détail de la génération

Ici nous allons générer un fichier par idée ("Topic") de la carte et un fichier supplémentaire pour la page de titre.

Nous adoptons une démarche de type "bottom-up" pour la création d'un générateur. Il s'agit dans un premier temps de réaliser un modèle d'exemple (ici une carte mentale) puis de coder manuellement les slides correspondants (on parle de "prototype").

Une fois ces deux premières tâches réalisées on va "industrialiser" et par conséquent réaliser les templates de génération permettant d'obtenir, à partir du modèle de départ, un résultat similaire au prototype. C'est cette phase que nous allons détailler, bien sûr nous allons générer ici du XHTML mais nous pouvons en utilisant la même méthode générer du code (C++, C, Python, Java ...).

Une fois la première phase d'industrialisation réalisée, il s'agit de vérifier le bon fonctionnement du générateur sur d'autres modèles afin de le valider et éventuellement de l'ajuster.

Les projets que nous allons développer dans le cadre de cet article peuvent être téléchargé, ils contienne un modèle d'exemple et le générateur XHTML complet.

Générateur XHTML pour MindMap

II.2. Projets

Nous divisons notre environnement de travail en deux projets distincts, le premier (free.demo.mindmap) contiendra notre carte mentale ainsi que le code généré. Le second (free.demo.mindmap.gen.xhtml) contient les templates de génération correspondants.

Le projet free.demo.mindmap est un projet de type simple que l'on peut créer au sein d'Eclipse en choisissant "General" dans l'assistant de création de projet.

Image non disponible
Création du projet free.demo.mindmap

Nous organisons le projet de la façon suivante : le repertoire model contient notre carte mentale correspondante au prototype. Ce dernier sera disponible dans prototype et nous aidera à mettre au point notre générateur tandis que le repertoire slides contiendra lui, le code généré.

Image non disponible
Organisation du projet free.demo.mindmap

Le projet free.demo.mindmap.gen.xhtml est un module de génération, il faut choisir "Acceleo generator" pour le créer au sein de l'environnement.

Image non disponible
Création du projet free.demo.mindmap.gen.xhtml

Ce projet accueillera tous les templates de génération nécessaires, ils seront placés dans le répertoire src.

Image non disponible
Organisation du générateur

Trois templates de génération ont été developpés (les fichiers .mt), nous les détaillerons plus loin.

II.3. Modélisation

Nous l'avons indiqué auparavant, nous adoptons une démarche de type "bottom-up" pour la création des générateurs. Ainsi il faut dans un premier temps réaliser une carte mentale et le code correspondant.

Plaçez-vous dans le repertoire model du projet free.demo.mindmap. Vous pouvez alors créer une nouvelle carte mentale en choisissant new puis other dans le menu contextuel.

Image non disponible
Création d'une nouvelle carte mentale

Vous pouvez ainsi créer votre carte mentale. Remplissez-là avec différentes idées que vous pouvez relier entres elles.

Image non disponible
Une carte mentale : Présentation d'Acceleo

Cette carte représentera notre base de travail pour la réalisation du prototype.

II.4. Prototype

Dans notre cas le prototype est donc un ensemble de slides réalisés en XHTML. Sa création permet de mettre en place le contenu d'un fichier type ainsi que les feuilles de style nécessaires.

Dans le cadre de cet article nous ne réalisons que 2 fichiers : le premier présente la page de titre (index.html) tandis que le second un exemple de slide.

Image non disponible
Prototype de slide en XHTML
Image non disponible
Code source du prototype

III. Un générateur pour MindMap

III.1. Un premier template

Nous allons tout d'abord rapidement présenter le fonctionnement d'Acceleo et la syntaxe de ses templates de génération.

Un template de génération est un patron qui se doit de délimiter de façon claire le texte statique généré et les éléments variables. Dans Acceleo cette limite est claire et facilite la lecture des scripts par une tierce personne. Le texte variable commence par <% et fini par %>.

Voici un exemple de template de génération. On y distingue plusieurs parties.

Image non disponible
Exemple de template de génération

La zone en entête définie sur quel méta-modèle ce template s'applique. Ici l'adresse correspond à celle de notre méta-modèle de carte mentale mais elle pourrai aussi bien être UML par exemple. Dans cette zone sont également réalisés des imports (pour appeler d'autre scripts ou du code Java).

Ensuite le template est divisé en un certain nombre de scripts. Le script est l'unité élémentaire d'un template. Il évalue un élément pour produire du texte. Chaque script s'exécute sur un type d'éléments donnés. Ainsi dans notre cas on va avoir des scripts s'exécutants sur Topic (qui correspond à une idée) tandis que d'autres concerneront tout le carte mentale (le type Map).

Nous allons dans un premier temps réaliser un template très simple. Ce dernier génère un fichier pour chaque Topic d'une carte mentale.

Pour créer un nouveau template, cliquez sur New puis Empty Generator.

Image non disponible
Nouveau template de génération

Ici nous voulons réaliser un template pour "MindMap". Il convient donc de sélectionner l'URI correspondante. L'URI permet d'identifier clairement les types de modèles que l'on va exploiter, ici il s'agit de http://www.obeo.fr/dsl/mindmap mais si l'on souhaite générer du code à partir d'UML par exemple on choisira l'URI http://www.eclipse.org/uml2/2.0.0/UML.

La liste déroulante Types values permet d'indiquer sur quel type d'objet on souhaite générer un fichier.

Ici on souhaite générer un fichier par Topic présent dans le modèle, on choisit donc le type Topic.

Image non disponible
Nouveau template de génération pour MindMap

L'assistant crée alors un template de génération vide.

Image non disponible
Template vide pour MindMap

La syntaxe d'Acceleo est extrêmement simple. Tout les caractères représentés en noir dans l'éditeur sont des zones statiques, elles seront recopiées telles quelles au sein du fichier généré. Les zones entourées des balises <% et %> sont des zones variables qui correspondent à l'évaluation de l'expression sur l'objet courant.

Autrement dit dans le fichier suivant l'expression <%title%> est automatiquement remplacée par le titre du Topic courant.

Vous pouvez d' ores et déjà expérimenter la réalisation de template, l'éditeur fourni avec Acceleo supporte la completion syntaxique et la détection d'erreurs ce qui aide considérablement à la réalisation de templates de génération.

Image non disponible
Un template simpliste pour MindMap

III.2. Prévisualisation du code généré

Maintenant que nous avons réalisé notre premier template, il est très pratique de voir le résultat d'une génération. En plus de l'éditeur de fichiers .mt Acceleo offre un outil extrêmement pratique pour la mise au point de templates de génération : l'éditeur réflectif.

Vous pouvez l'ouvrir en cliquant avec le bouton droit sur le fichier contenant la carte mentale (d'extension .mindmap) et en choisissant Open as->Acceleo XMI.

Image non disponible
Ouverture du modèle avec l'éditeur reflectif

L'éditeur réflectif est associé par défaut aux fichiers d'extension "xmi", "ecore", "uml" et "uml2". Dans le cas où votre modèle utilise une autre extension vous pouvez l'ouvrir avec l'éditeur réflectif en utilisant le menu "Open As -> Acceleo".

Le modèle est alors représenté sous une forme arborescente. On y retrouve la carte mentale, les Topic et les Relationship liant les topics entre eux.

Image non disponible
Éditeur reflectif avec le modèle de carte mentale

L'éditeur reflectif permet la prévisualisation en temps réel du code généré. Une fois le modèle ouvert dans l'éditeur réflectif il faut lui associer le template créé précédemment. Cliquez sur "Acceleo" -> "Select Template" dans l'éditeur réflectif et choisissez le template de génération que nous avons réalisé.

Image non disponible
Sélection d'un template de génération

Une fois le template sélectionné des marqueurs apparaissent dans la vue "Outline" de l'éditeur réflectif.

Image non disponible
Marqueurs de génération

Ces marqueurs signifient que le template peut génèrer un fichier pour chacun des objets marqués.

Lorsque l'on sélectionne un Topic disposant de ce marqueur l'éditeur réflectif affiche une prévisualisation du code généré dans l'onglet "source" (sur la gauche).

Modifiez le template de génération, choisissez dans l'éditeur reflectif Acceleo -> Reload Template et l'onglet source sera mis à jour.

En itérant de cette manière vous pouvez affiner le contenu des fichiers générés. Nous allons maintenant détailler de manière plus précise la syntaxe des expressions entre balises <%%>.

La syntaxe des expressions est une notation pointée extrêmement simple. Elle est contextuelle au type de l'objet courant. Ainsi l'expression suivante évaluée sur un objet de type Map

 
Sélectionnez
ownedTopics

fourni la liste de tous les Topics contenus dans la carte mentale.

L'expression suivante :

 
Sélectionnez
ownedTopics.title

renvoi la liste des titre des topics contenus dans la carte mentale.

La figure suivante détaillé un cas concret d'utilisation : on souhaite générer le contenu des Topic (sous la forme de paragraphes). Ainsi on itère sur la liste des Thread contenus dans le Topic.

Image non disponible
Itérations et appels de sous-scripts

Pour chacune des itération on génère une division qui contiendra autant de paragraphes que le Thread contient de ThreadItem.

Ensuite dans le script content on traite le cas où le Topic possède un certain nombre d'autres sous-topics. Ils apparaissent alors sur ce slide sous la forme de divisions.

La ligne

 
Sélectionnez
subTopics.target.itemTopic

déclenche l'appel d'un sous-script : "itemTopic" pour chacun des subTopic du Topic courant.

La figure suivante montre un exemple de code généré via ces deux scripts.

Image non disponible
Code généré par l'itération et l'appel de sous-scripts

III.3. Notation pointée et navigation dans le modèle

Nous allons désormais détailler un peu plus précisemment le fonctionnement de cette syntaxe.

Par cette notation pointée nous pouvons donc indifféremment accéder à des attributs des objets (récupérer le titre d'un Topic) ou accéder à d'autres objets liés au premier.

Ainsi dans l'exemple suivant le template

 
Sélectionnez
ownedTopics.topic2Xhtml

Renvoi le code généré depuis tous les Topics par le script topic2Xhtml.

Il est également possible d'appeler de la même façon des services codés en Java. Un certain nombre de services utiles pour une navigation aisée dans le modèle sont fournis avec Acceleo. Il est également possible de coder ses propres services très simplement, nous en verrons un exemple plus loin.

 
Sélectionnez
ownedTopics.nFirst.topic2Xhtml

Renvoi le code généré à partir du premier Topic par le script topic2Xhtml.

 
Sélectionnez
eAllContents("ThreadItem")

Renvoi la totalité des objet de type ThreadItem contenus dans la descendance de l'objet courant.

Il est également possible de sélectionner certains éléments en fonctions de critères par le biais du service select. Ainsi :

 
Sélectionnez
eAllContents("Topic").select("ownedThreads.nSize > 0")

Sélectionne tous les descendants de type Topic contenant au moins un Thread.

Pour plus d'informations et pour avoir une liste détaillée des services fournis avec Acceleo, reportez vous à la documentation de référence et aux projets d'exemple.

Documentation de référence Acceleo

Nous n'exposerons volontairement pas dans le détail la totalité des templates de génération ici. Vous êtes invité à faire vos propres templates en prennant exemple sur les projets de démonstration fournis.

IV. Notions avancées

IV.1. Génération massive des slides

Nous allons maintenant mettre en place la génération massive de fichiers. Notre générateur est constitué de 3 templates :

Image non disponible
Templates du projet de génération

slide.mt : génère pour chaque Topic le fichier XHTML correspondant au slide.

index.mt : génère pour chaque carte une page de titre des slides.

common.mt : défini des scripts communs utilisés par les deux templates précédents.

Il est possible d'importer des scripts au sein d'autres script par le biais de l'instruction import que l'on peut positionner dans l'entête du template.

Il est temps désormais de lancer une génération qui créera réellement les fichiers. Chaque script conduisant à la création d'un fichier possède un attribut file. Cet attribut est une expression évaluée sur l'objet courant.

Image non disponible
Script et balise file

Il est possible de lancer la génération sans avoir besoin de l'éditeur réflectif par le biais d'une chaîne de lancement (fichier .chain).

Créez une chaîne de lancement via le menu New->chain. Exécutez l'assitant, à la fin de ce dernier un fichier est crée, il permet l'enchainement de générations. Pour ajouter une opération de génération il faut d'abord ajouter le template correspondant dans le repository du fichier.chain puis ajouter une nouvelle action de génération.

Modifiez le fichier afin d'obtenir un résultat similaire à la figure suivante.

Image non disponible
Chaîne de génération massive

Une fois le fichier .chain complété, vous pouvez cliquer avec le bouton droit dessus et choisir Launch. Ceci va déclencher le lancement de la génération et les fichiers vont apparaitres dans le repertoire slides.

Image non disponible
Fichier générés

Ainsi vous pouvez maintenant tester l'enchaînement des différents slides et effectuer les ajustements nécessaires dans les templates.

IV.2. Génération incrémentale

Acceleo permet la génération incrémentale. Cela signifie qu'il est possible de compléter le code généré (ici du XHTML), puis de re-générer sans perdre les modifications apportées auparavant.

Le code pouvant être modifié par les développeurs est entouré de balises utilisateur. Ces balises ne polluent pas le code cible car elles se présentent sous la forme de commentaires explicites. A la génération suivante, tout ce qui sera entre les deux balises sera conservé.

Nous allons ici définir une telle zone pour chaque slide afin que l'utilisateur puisse ajouter, par exemple, une illustration au sein d'un slide.

Image non disponible
Template avec zone de code utilisateur

Relancez la génération. Modifiez le code généré entre ces deux balises. Re-générez, vous constatez que le code utilisateur n'est pas perdu.

Image non disponible
Fichier XHTML avec code utilisateur

IV.3. Ajustements

Nous allons maintenant réaliser quelques ajustements à notre génération. Le premier consiste est l'insertion de la date de génération dans les slides, ceci passe par la réalisation d'un service Java.

Pour créer un service Java il suffit de placer un fichier .java dans le repertoire src du générateur.

Créez un nouveau package, nous le nommons ici "services". Créez ensuite une nouvelle classe au sein de ce package.

Image non disponible
Nouveau service

Les méthodes de cette classe représentent autant de services qui peuvent être utilisés pendant la génération.

Le premier paramètre de la méthode représente l'objet sur lequel le service est disponible. Ainsi si l'on spécifie un type String on ne pourra appeler le service que sur des chaînes de caractères.

La figure suivante détaille le service now(). Ce dernier renvoie une chaîne de caractère correspondant à la date courante.

Image non disponible
Service now()

Ce service est définit sur le type ENode. Cela signifie que l'on peut l'appliquer sur n'importe quel type d'objet. Le second service : "noSpecials" enlève tous les caractères spéciaux d'une chaîne. Ce dernier s'applique sur le type String.

Vous pouvez désormais importer ce service au sein du template par le biais de l'instruction import.

Image non disponible
Import d'un service Java

Le service now() est alors disponible.

Image non disponible
Utilisation du service now()
Image non disponible
Index avec date de génération

IV.4. Résultat

Nous avons désormais un générateur de slides XHTML depuis une carte mentale. Vous pouvez vous faire une idée de la génération obtenue en consultant l'exemple de slides mis en ligne.

Exemple de slides générés

Cet exemple à pour but principal de faciliter la compréhension du fonctionnement d'Acceleo et de la mise en place de template de génération.

Nous avons ici généré du XHTML à partir d'un modeleur de carte à idées, le processus est exactement le même pour générer du code (Java, Python ou autre...). Des projets d'exemples sont disponibles sur le site d'Acceleo, ils contiennent des générateurs de code Java (DTO, DAO, Jsp) et présentent une utilisation plus poussée des templates et des services Java.

Modules d'exemples Acceleo

V. Conclusion

V.1. Industrialisation du développement et génération de code

L'utilisation de cette approche a de nombreux avantages. Elle apporte tout d'abord une certaine indépendance vis à vis de la plateforme technologique. Ainsi si nous souhaitons migrer nos slides vers une autre technologie (SVG par exemple) il suffit de réaliser un générateur pour SVG et l'on pourra indifféremment générer du XHTML ou du SVG.

De plus l'utilisation de templates de génération fait que le code généré est cadré et respecte donc les standards que l'on souhaite établir (tant d'un point de vue du formatage que de l'architecture).

Il est également important de noter que les templates permettent la capitalisation du savoir technique. En effet une personne sans connaissance particulière de XHTML sait désormais générer des slides via cette technologie en utilisant un générateur.

De plus la maintenance est facilitée, on obtient une vrai synchronisation entre le code et le modèle. Ce dernier passe du statut de modèle documentaire à celui de modèle productif.

Enfin cette approche couplée aux modeleurs spécifiques permet de définir son propre modeleur constitué d'un nombre réduit de concepts, juste assez riche pour permettre une génération intéressante et juste assez léger pour ne pas remplacer le code.

Ces modeleurs permettent d'avoir une vision plus proche des besoins fonctionnels, Acceleo permet l'exploitation et la valorisation de ces informations.

V.2. Références

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Copyright © 2006, Obeo. Tous droits réservés.