IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Un premier exemple d'utilisation d'Eclipse Xpand

Publié le 1 janvier 2012 et mis à jour le 4 juillet 2012

Par Jérémie BressonSite personnelBlog

 

Cet article propose un exemple simple de prise en main d'Eclipse Xpand.
À partir d'un fichier XMI contenant les données correspondant à un métamodèle d'annuaire, Xpand sert à générer quelques pages HTML

       Version PDF   Version hors-ligne   Version eBooks
Viadeo Twitter Facebook Share on Google+        





I. Introduction

Xpand fait parti des outils Model to Text (M2T) d'Eclipse EMF. Il s'agit de transformer un modèle en fichier texte, ces fichiers constituants souvent les sources d'une application java (Eclipse oblige). Cependant le format de sortie importe peu, et tout est imaginable tant que c'est du texte. Par exemple, dans cet article, on génèrera des fichiers HTML (plus simple et plus visuel que du code source). Dans la même famille d'outils (M2T) on trouve Acceleo (édité par les français d'Obeo), ainsi que JET (méthode et concepts plus anciens, à déconseiller pour de nouveaux projets).

Cet article ne revient pas sur les concepts EMF (ecore, xmi) avec lesquels le lecteur doit être familier. L'exemple utilisé dans l'article provient de support de cours Modélisation via EMF de Mickaël BARON. Il s'agit du même fichier addressbook.ecore (à quelques conventions de nommage près), et d'un jeu de données pour ce modèle (comme le fichier xmi créé avec le test unitaire). Ces deux fichiers sont redonnés en annexe, au besoin il est possible de créer ces fichiers vierges, de les ouvrir avec l'éditeur de texte et de copier-coller leur contenu.

Xpand repose sur plusieurs types de fichiers. Pour cet article, deux d'entre eux sont abordés: les fichiers templates (*.xpt) et les fichiers workflow (*.mwe). Les fichiers templates vont définir les transformations du modèle vers le format texte. On retrouvera ici tout ce que l'on attend de ce type de fichier: quelques instructions pour lancer des boucles en itérant sur des listes, créer des fichiers, accéder aux propriétés d'un modèle, ajouter des branches if-else et ainsi de suite... Les fichiers workflow sont chargés de lancer les transformations. Dans une syntaxe XML (qui me fait un peu penser à ANT), on indique quels modèles doivent être lus et quels fichiers template doivent être utilisés.

Dernier prérequis de cet article: avoir une version d'Eclipse installée configurée pour Eclipse Modèling et Xpand. Pour ce faire, le plus simple est de télécharger Eclipse Modeling Tools sur la page des téléchargements d'Eclipse, puis d'installer Xpand par le Eclipse Modeling Components Discovery.

Eclipse Modeling Components Discovery

II. Objectif du projet

Nous partons d'un fichier Ecore qui modélise un carnet d'adresses simple. La EClass principale AddressBook contient un attribut nom, ainsi qu'un nombre illimité de personnes (EClass Person). La EClass Person contient un prénom, un nom, un âge et une adresse (EClass Address). La EClass Address contient un numéro de rue et un nom de rue.

Diagramme représentant le modèle Ecore addressbook
Pour les données (le fichier XMI), nous disposons d'un petit carnet d'adresses contenant quelques écrivains connus ***A préciser***.

L'idée est d'obtenir une version HTML de notre carnet d'adresses. Une page principale liste toutes les personnes du carnet d'adresses. Chaque personne dispose ensuite de sa page avec les données plus détaillées.


III. Première version minimale

Il semble important d'obtenir un projet fonctionnel pour pouvoir faire des essais. Cette partie détaille comment obtenir un projet expand muni d'un template minimaliste (transformation très simple) et d'un workflow pour lancer la transformation.


III.1. Création du projet Xpand

La création du nouveau projet passe par l'assistant habituel à la création de tout projet dans Eclipse (New > Project...). Dans l'arbre proposé sélectionner Xpand > Xpand Project. A l'étape suivante, donner un nom de projet (par exemple org.ekzemplo.adb.generat) et laisser les réglages standards (Use workspace defaults).

Il faut maintenant copier les fichiers addressbook.ecore et ecrivains.xmi dans le dossier src du projet. Pour rappel ces fichiers sont fournis en annexe de cet article.


III.2. Création d'un fichier template simple

Le projet ainsi créé contient déjà un dossier src. Dans ce dossier nous allons ajouter un fichier template. Choisir New... > Other... puis sélectionner Xpand template. Donner un nom au fichier: "TemplateFile.xpt" et valider.


III.2.a. Utilisation des guillemets

Comme dans de nombreux systèmes de templating, on retrouve des caractères permettent de séparer les instructions du texte. Dans Xpand il s'agit des guillemets « et ». Tout ce qui se situe à l'extérieur est considéré comme du texte simple, tout ce qui se situe à l'intérieur sera interprété. Pour facilité la saisie de ces caractères, l'éditeur de template d'Eclipse propose plusieurs choix grâce au raccourci CTRL + Barre espace.

Pour éviter tout problème d'interprétation du fichier, il faut privilégier un système d'encodage de ces deux caractères qui fonctionne selon ce qui est attendu. C'est le cas de UFT-8 ou ISO-8859. (Les utilisateurs de Mac devront faire attention à leurs réglages)


III.2.b. DEFINE ... ENDDEFINE

Les blocs define constituent la structure de base des templates. Le bloc est encadré par une opération «DEFINE definionName FOR Type» et se termine par «ENDDEFINE». Lors de l'opération ouvrant le bloc, il faut au minimum définir le nom du bloc (definitionName) ainsi qu'un type pour lequel le bloc est défini (Type). Il est également de passer une liste de paramètres (de manière analogue au Java), nous y reviendrons plus tard.

Nous allons donc définir un bloc nommé "main" qui s'utilisera avec une instance de AddressBook. Cette entité étant définie dans le package ecore addressbook, il faut définir le type comme "addressbook::AddressBook".

Pour toutes les déclarations (Type, Import, référence...), le séparateur utilisé est constitué deux double-points consécutif "::".


III.2.c. FILE ... ENDILE

Un autre bloc très utile est celui qui permet de définir la création d'un fichier. Le bloc est encadré par une opération «FILE fileName» et se termine par «ENDFILE». Le nom de fichier doit être défini par une expression de type String (soit une constante soit le résultat de l'évaluation d'une opération). Pour atteindre un sous-dossier, le séparateur "/" est utilisé dans la chaine de texte.

Dans notre exemple, nous voulons créer un fichier index.html à la racine. "index.html" sera la valeur constante qui sera utilisée comme fileName. On va donc définir un petit fichier HTML minimal à l'intérieur du bloc. Le code sera chargé d'afficher un titre défini dans la balise title et un titre dans le body HTML à l'aide d'une balise h1.


III.2.d. Accès aux propriétés de l'instance

Nous avons vu que le bloc DEFINE est défini pour un type donné. Au moment de l'évaluation de la transformation, il est possible d'accéder à l'instance pour laquelle le bloc est évalué grace au mot clé "this" (de manière analogue au java).

Dans notre exemple, le bloc DEFINE est évalué pour une instance d'AddressBook. Nous aurons accès au nom de l'annuaire grace à "«this.name»".


III.2.e. Résultat

Mis ensemble, les différents éléments présentés dans cette partie permettent d'obtenir le fichier TemplateFile.xpt suivant:
«DEFINE main FOR addressbook::AddressBook»
«FILE fileName»
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<html lang="en">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<title>«this.name»</title>
</head>
<body>
	<h1>«this.name»</h1>
</body>
</html>
«ENDFILE»
«ENDDEFINE»
Première version de TemplateFile.xpt dans l'éditeur Eclipse

III.3. Création du workflow

Il s'agit maintenant d'ajouter un workflow permettant de lancer la transformation que nous avons précédemment définie. Toujours dans le dossier src créer un nouveau fichier (New... > Other...) de type Workflow File. Nommer ce fichier "Generator.mwe".

Le fichier workflow est écrit au format xml. La racine de ce fichier est une balise "workflow" qu'il s'agit d'ajouter:
<workflow>
</workflow>

III.3.a. Définition de propriétés

Les premiers éléments que nous allons ajouter vont nous permettre de définir quelques propriétés (qui seront réutilisées à plusieurs endroits au sein du workflow). De manière très standard il s'agit d'association {nom, valeur} définie dans grâce à la balise "property" contenant les attributs "name" et "value". Dans le reste du workflow les propriétés sont accessibles par "${nom_de_la_propriété}" (par exemple ${srcGenPath} pour la propriété srcGenPath).
  <property name="modelFile" value="..chemin_vers_le_workspace../org.ekzemplo.adb/model/myaddressbook.xmi"/>
  <property name="srcGenPath" value="src-gen"/>
Il est également possible de définir les propriétés dans un fichier séparé (*.properties). Dans ce cas, une balise property avec l'attribut file pointant vers ce fichier est nécessaire.


III.3.b. Bean et GeneratedEPackage

Il s'agit maintenant d'ajouter quelques configurations pour ce fichier Workflow. Ceci est réalisé par la balise "bean" (ainsi que les balises enfants). Nous indiquons entre autres le chemin vers le fichier ECore (avec la balise registerEcoreFile).
  <bean class="org.eclipse.emf.mwe.utils.StandaloneSetup" > 
    <platformUri value=".."/> 
    <registerEcoreFile value="..chemin_vers_le_workspace../org.ekzemplo.adb.generator/src/addressbook.ecore"/>
  </bean>

III.3.c. Lecture du fichier xmi

*
  <component class="org.eclipse.emf.mwe.utils.Reader"> 
    <uri value="file://${modelFile}" /> 
    <modelSlot value="addressbookData" />
  </component>

III.3.d. Netoyage du dossier src-gen

  <component class="org.eclipse.emf.mwe.utils.DirectoryCleaner">
    <directory value="${srcGenPath}" />
  </component>

III.3.e. Définition de la transformation

Utilisation du template Generation du HTML à l’aide du Template.
  <component class="org.eclipse.xpand2.Generator">
    <metaModel id="mm" class="org.eclipse.xtend.typesystem.emf.EmfRegistryMetaModel"/>
    <expand value="TemplateFile::main FOR addressbookData"/>
    <outlet path="${srcGenPath}" />
  </component>

III.3.f. Execution et résultat

Run as...


IV. Amélioration du template

La partie précédente nous a permis d'obtenir un projet fonctionel muni d'une transformation très simple. Dans cette partie, le fichier template va être amélioré pour obtenir le résultat souhaité. Cela permettra d'aborder d'autres notions importantes utilisées dans les fichiers templates.

* «IMPORT adb»

* Appel d’une autre boucle EXPAND FOREACH + définition

* Fin de ligne -

* Tri de la collection {'C','B','A'}.sortBy(e | e) == {'A','B','C'} {'AAA','BB','C'}.sortBy(e | e.length) == {'C','BB','AAA'} {5,3,1,2}.sortBy(e | e) == {1,2,3,5} {5,3,1,2}.sortBy(e | e - 2 * e) == {5,3,2,1}

* «EXTENSION org::eclipse::xtend::util::stdlib::uid» -> Ajouter la dépendance -> utiliser la function

* EXPAND person_page avec un paramètre

* parametric polymorphism pour table_row

* Lien rapide en haut de page pour atteindre un élément: définition de variables


V. Résultat et résumé

***


VI. Remerciements

Je tiens à remercier l'équipe de developpez.com pour leurs précieux conseils, suggestions ou corrections, et tout particulièrement keulkeul.


VII. Annexes

En annexe, se trouve les fichiers ecore et xmi correspondants à cet exemple. Le projet réalisé est disponible sur GitHub ***. On trouvera à cet endroit également d'autres projets autour du même exemple emf.


V.1. Fichier .ecore

<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="addressbook" nsURI="http://ekzemplo.org/addressbook/1.0" nsPrefix="addressbook">
  <eClassifiers xsi:type="ecore:EClass" name="AddressBook">
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="persons" upperBound="-1"
        eType="#//Person" containment="true"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Person">
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="firstName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="familyName" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="age" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
    <eStructuralFeatures xsi:type="ecore:EReference" name="location" lowerBound="1"
        eType="#//Address" containment="true"/>
  </eClassifiers>
  <eClassifiers xsi:type="ecore:EClass" name="Address">
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="number" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
    <eStructuralFeatures xsi:type="ecore:EAttribute" name="street" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
  </eClassifiers>
</ecore:EPackage>
				

V.2. Fichier .xmi

****



               Version PDF   Version hors-ligne   Version eBooks

Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2012 Jérémie Bresson. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.