Définition d'une transformation Model To Model
Nous voulons décrire comment passer d'un automate conforme au métamoèle FSM à un automate conforme au métamodèle FSM4Code. Il s'agit d'une transformation Model to model ou M2M, que nous allons décrire en QVT Operational. QVT Operational est une implémentation des aspects opérationnels du standard QVT (Query/View/Transformation) de l'OMG. Il existe d'autres langages de description de transformations M2M, un des plus connus étant ATL.
Nous allons donc créer un nouveau projet QVT Operational, en choisissant l'élément indiqué ci-dessous dans ''File > New > Project…' :

Vous pouvez conserver tous les réglages par défaut, sauf dans le dialogue ci-dessous où il faudra choisir de créer une transformation :

Le plus simple pour écrire la transformation est ensuite d'effacer le contenu du fichier qvto créé, et de le remplir en utilisant la complétion automatique (activée par le raccourci Ctrl-espace).
Vous devez tout d'abord déclarer les métamodèles source et cible à l'aide du mot-clef modeltype en utilisant la complétion automatique (le raccourci est Commande-espace sur Mac, Contrôle-espace sous Linux et Windows) afin que les références soient correctes dans le modèle (le copier-coller de texte ne suffit pas). Une fois la complétion automatique utilisée, vous devriez avoir des déclarations comme ci-dessous (au nom des types près) :
Vous déclarez ensuite la transformation, avec son modèle d'entrée et son modèle de sortie, ainsi que son point d'entrée, main :
La transformation est définie comme un ensemble d'applications de transformations élémentaires. Ici, le point d'entrée indique qu'il faut prendre les éléments racines (rootObjects) du modèle d'entrée, et leur appliquer la transformation toCode(). Il faudra définir cette transformation pour chacun des types d'objet auxquels nous allons l'appliquer. Voici, pour vous aider à démarrer et pour connaître les éléments syntaxiques nécessaires, la transformation de l'élément racine StateMachine. Il vous restera à définir la transformation pour les States et les Transitions :
La ligne 1 indique qu'il s'agit de la transformation toCode() qui, appliquée à une instance de StateMachine du métalmodèle SRC, produit une instance de StateMachine du métamodèle DST. Les lignes 2 et 3 utilisent une requête OCL pour vérifier que le nombre d'états qui sont initiaux est strictement égal à 1, sinon, la transformation est arrêtée avec un message d'erreur.
Les lignes suivantes établissent la correspondance (mapping) entre les deux types d'objet. Le mot clef result désigne l'objet produit, le mot clef self désigne l'objet source. Il est possible d'utiliser OCL pour naviguer dans le modèle et sélectionner des éléments, comme illustré avec select et collect. il est aussi possible d'appliquer des transformations en utilisant map.
Un élément important pour établir les liens entres objets dans le modèle produit est d'être capable de retrouver un objet produit par une transformation à partir d'un objet source. C'est le but des primitives resolveIn et resolveoneIn. Ainsi, la ligne 9 trouve l'état initial du modèle cible en recherchant l'état produit par la correspondance State::toCode à partir de l'état initial de l'automate source. On peut ici utiliser resolveoneIn puisqu'on a vérifié au début de la transformation que l'état initial est unique et que les correspondances de cette transformation ne produisent qu'un objet dans le modèle cible pour chaque objet du modèle source. Une variante des opérateurs de résolution utilise le mot clef late pour indiquer que la résolution doit être faite tardivement (comme dans une deuxième passe), une fois que tous les objets cibles ont été créés. Elle vous sera utile dans la transformation des transitions (la syntaxe est late resolveoneIn(...)).
Exécution de la transformation
Pour exécuter cette transformation sur notre automate, il suffit de choisir Run As > Run Configurations… dans le menu contextuel du fichier .qvto, et de créer une configuration QVT Operational Transformation puis de renseigner les modèles source et cible dans le dialogue qui s'affiche :

Vous obtiendrez un fichier .xmi contenant le modèle cible, que vous pouvez inspecter comme le modèle source dans le Sample Reflective Ecore Model Editor.