Using Acceleo with GMF
Acceleo 1.1 has been released and is compatible with Eclipse 3.2 and the new and promising GMF Framework. This tutorial demonstrates how Acceleo can be deployed with GMF to achieve a MDE platform based on “Domain Specific Modelers”. Using these technologies will allow users to create customized specific modelers and to generate code, text or documentation through Acceleo. In this article we will see how to realize an XHTML slide code generator from a mind map.
- Environment setup
- A MindMap generator
- Advanced concepts
By Cédric Brun, Obeo (France)
13 oct. 2006 14:57:59
This article is about using the Acceleo code generator with Domain Specific Modelers. One can see it as the next step of the GMF tutorial that deals with creating a DSM : a “MindMapping”. This modeler is one of the simplest you can imagine, it's just about putting down ideas and linking them together.
In this article we will detail how to realise a code generator for this “MindMapping” tool. The goal is to generate slides (using XHTML) from a mind map, having each main idea translated into a slide, and every sub-idea listed inside each slide.
You may want to look at an example of generated slides through the next url. Moreover, all projects used for this article are available for download.
First you should install Acceleo and its dependencies including GMF which enables the use of DSMs. A bundle is available on the Acceleo web site (bundle-emf-uml2-gmf-acceleo-1.1.0), and is all set for Acceleo and GMF combined use.
Should you need more information on how to install Acceleo, please refer to the instructions available on the Acceleo web site.
To check that everything is properly set-up, just check that there is a new perspective available within Eclipse and select it.
This article is also based on a plugin realised with the GMF project. This plugin contains the MindMap modeler.
The GMF project offers detailed explanations about how to design this modeler. You are invited to read it if you want to realize your own specific modeler later on. Here we will show how to use it. We have compiled this plugin based on the same meta-model, download it and unzip it under your Eclipse installation folder.
If the plugin is not working properly in your Eclipse environment, you may have to close Eclipse, delete all folders under the “configuration” folder of Eclipse, and then restart Eclipse.
You may check that the MindMapping tool is properly installed by creating an empty project and choosing “File”, “New” then “Other” within Eclipse. A category “Obeo Domain Specific Modeler” should be available, it allows the creation of a new mind map.
The overall picture of generation is the following : Acceleo uses a template to generate code (or text) from a model. In our exemple, the model is a mind map, and the generated code is a set of XHTML files that corresponds to the slides you will obtain.
Here we will generate one file per idea (“Topic”) of the map and another file for the title page.
We will use a “bottom-up” approach for creating the generator. First, we will design a model sample (here a mindmap sample) and then we will code manually the corresponding slides (hereafter referred to as "prototype").
Once these two first tasks are finished, we are going to “industrialize” the process, i.e. realize template generators that will generate a result close to the prototype based on an input model. This is what we are going to detail in this tutorial, of course we are going to generate XHTML but you may use the same method to generate code (for example C++, C, Python, Java...).
Once the first phase of industrialization is done, we have to check that the generator is working properly using other models, and we may fix this generator.
Projects that we are going to develop in this tutorial may be downloaded, they contain a model example and the complete XHTML generators.
We divide our workspace into two separate projects, the first (free.demo.mindmap) holds the mind map model as well as the generated code, the other (free.demo.mindmap.gen.xhtml) holds the corresponding generation templates.
The free.demo.mindmap project is a straight project that can be created within Eclipse by choosing “General” in the project creation wizard.
We organize the project in the following way : the model folder contains the mind map corresponding to the prototype. The prototype will be available in the prototype folder and it will help us in designing our generator, and the slide folder will hold the generated code.
The free.demo.mindmap.gen.xhtml project is a generation module, you have to choose “Acceleo Generator” to create it in your workspace.
This project will hold all required template generation, they will be placed under the src folder.
Three generation templates have been developed (.mtfiles), we will detail them later on.
As we said earlier, we are adopting a bottom-up approach for the generator creation. So we will first realize a mind map and the corresponding code.
Go under the model folder of the free.demo.mindmap project. You may then create a new mind map by choosing new then other in the contextual menu.
You may then create your own mental map. Fill it with the different ideas that you may link together.
These maps will represent our base for realizing the prototype.
In our case study, the prototype is a set of slides in XHTML. Its creation enables us to have an example of how a slide is made as well as its required stylesheets.
In the context of this article, we will design 2 different type of files : the first is the title page (index.html) and the second is a slide example.
We will first quickly introduce how Acceleo works and how to write generation templates
A generation template is a pattern that should show clearly properly static text from variable elements
Here is an example of a generation template. We can distinguish different parts.
The heading section defines which meta-model the template will apply for. Here the URI corresponds to the one of our mind map meta-model, but it could be another one like UML for example. Imports (to include other templates or Java Services) are also put in this section.
Then the template is divided into a certain number of scripts. A Script is the elementary unit of a template. It is applied on a model element to produce some text. Every script will be evaluated on a given element type. In our case, we will have scripts applying to the Topic element (referring to an idea) and the Map element (referring to the whole mental map).
We will first realize a very simple template. This template generates a file for each Topic of a mental map.
To create a new template, click on New then Empty Generator.
Here we want to realize a template for “MindMap”. We have to select the appropriate URI. The URI helps in identifying clearly what type of model you are working on. Here, it is http://www.obeo.fr/dsl/mindmap but if you want to generate code from UML for example, you may replace it for the URI http://www.eclipse.org/uml2/2.0.0/UML.
The drop-down list Types values indicates on which object type the file will be generated.
Here we want to generate one file per Topic present in the model, so we choose the Topic type.
The wizard creates an empty generation template.
The Acceleo syntax is extremely simple. All characters represented in black in the editor are static areas, they will be generated as is in the generated file. Areas surrounded by <% and %> signs are dynamic areas that corresponds to the expression evaluation on the current object.
In the following example, the expression <%title%> is automatically replaced by the title of the current Topic.
You may already test how to design an Acceleo template, the editor provided by Acceleo deals with syntax highlighting and error detection, which helps a lot when designing generation templates.
Now that we have realized our first template, it is very useful to see the result of a generation. On top of the template editor for .mt files, Acceleo provides a very useful and powerful tool for template realisation : the reflective editor.
You may open it by clicking with the right button on the file containing the mind map (.minmap extension) and by choosing Open as->Acceleo XMI.
The reflective editor is associated by default with extension files "xmi", "ecore", "uml" and "uml2". In the case when your model uses another extension, you may open it using the reflective editor using the "Open As -> Acceleo" menu.
The model appears as a tree. We can see the mind map with Topic and Relationship liking topics together.
The reflective editor enables real time preview of generated code. Once the model is opened with the reflective editor, you may associate it with the template previously created. Click on “Acceleo” -> “Select Template” in the reflective editor and choose the generation template we've just written.
Once the template is selected, markers appears in the “Outline” view of the reflective editor.
These markers mean that one file will be generated for each object..
If you select a Topic having this marker, the reflective editor displays a preview of the generated code in the “source” tab of the model (on the left)
Modify a generation template, right click inside the reflective editor and choose Acceleo -> Reload Template and the “source” tab will be updated.
Continuing this way, you will be able to tweak the result of the generated files. We are now going to detail more precisely the syntax of expressions that are between the tags <%%>.
The syntax of expressions is a very simple pointed notation. It is contextual to the current object type. The following expression is evaluated on a Map type object:
will give the list of all topics hold in the mindmap.
The following expression:
gets the list of topic titles contained in the mind map.
The next figure details a concrete use case: we wish to generate the content of Topic (to get paragraphs). So we iterate on the list of Thread contained in Topic.
For each iteration we generate a part that will contain as many paragraphs as the current Thread holds ThreadItem.
Then in the script content we deal with the case when Topic holds other sub-topics. They appear in the slide as divisions.
will call a sub script : itemTopic for every subTopic of the current Topic.
The next figure shows an example of generated code with those two scripts.
We will now detail more precisely how this syntax operates.
Thanks to this pointed notation, we can access object attributes (getting the title of a topic for example) or access any other object linked to the first one.
The following example :
returns the generated code from all the Topics by the topic2Xhtml script.
It is also possible with this same syntax to call services coded in Java. Some services allowing easy model navigation are provided with Acceleo. It is also possible to code your own Java services very easily, we will see that later on.
returns the generated code from the first Topic by the script topic2Xhtml.
returns all the objects of type ThreadItem contained in the children of the current object.
It is also possible to select some elements depending on criteria using the service select :
eAllContents("Topic").select("ownedThreads.nSize > 0")
Selects all children of the Topic type having at least one Thread.
For further information and to have a detailed list of services provided with Acceleo, please refer to the reference documentation and to the project examples.
On purpose, we will not explain in detail all templates used here. You are invited to do your own templates by taking example on the demonstration project provided here.
We will now setup massive file generation. Our generator is made up of 3 templates.
slide.mt : generates for each Topic the corresponding XHTML slide file.
index.mt : generates for each map a title page.
common.mt : defines common scripts used by the two preceding templates.
It is possible to import scripts within other scripts using the import instruction that you may use in the header of a template.
It is now time to launch a generation that will actually create the files. Each script creating a file has a file attribute. This attribute is actually an expression evaluated on the current object.
It is possible to kick off generation without using the reflective editor, by using a launching chain (.chain file).
Create a launching chain using the New->chain menu. Follow the wizard's steps and the .chain file will eventually be created. To add a generation operation, you first need to add the corresponding template in the repository of the .chain file then add a new generation action.
Modify the result to obtain a result close to the following figure :
Once the .chain file is complete, you can right click on it and choose Launch. It will start the generation and files will appear in the slides folder.
Now you can visualize the different slides and may modify some templates according to your needs.
Acceleo offers incremental generation support. This means that it is possible to complete code once it has been generated (here this is XHTML), then generate again without losing any of the modifications made by hand.
The code that may be modified by developers is surrounded by user tags. These tags do not pollute target code as they are explicit comments. On the next generation, all text which is nested between two user tags will be kept as is.
We are going to define here such an area at the end of every slide so that the user may add an illustration to the slides for example.
Launch the generation again. Modify code between user tags. Generate again, and you will see that the user code is not removed.
We are now going to tweak our generator. First we are going to insert a date in the generated slides, using a Java service.
To create a Java service, you just have to create a .java class in the src folder of the generator.
Create a new package, let's name it “services”. Then create a new class inside this package.
The class' methods represent services that may be used for generation.
The first parameter of the method represents the object on which the service is available. If you specify a String type, then the service may be called only on Strings.
The next figure shows the now() service. It returns a String corresponding to the current date.
This service is defined on the ENode type. This means that you may apply it on any object. The second service “noSpecials” removes any special character from a String. It applies on the String type.
You can now import this service in a template using the importinstruction.
The service now() is then available.
We now have an XHTML slide generator from a mind map. You may see what the generated result looks like by having a look at the following on-line slides :
This sample was made to ease the understanding of Acceleo and how to set up generation templates.
Using this approach gives many advantages : it brings some independence from the technical platform. We may generate the same slides targeting another technology (SVG for example) by designing another SVG code generator, and then you could choose between SVG or XHTML generation.
Moreover, using generation templates improve code quality and reliability so it helps in making sure that standards are properly used from an architectural and coding point of view.
It is also important to stress that templates enable technical reuse. Indeed, somebody who doesn't know about XHTML will still be able to generate slides in this technology by using a code generator.
Maintenance is also eased, by having a real mapping between model and code. Now models can become productive and not just documentation.
Finally, this approach may be used using Domain Specific Modelers (like the mindmap) where used artefacts are very limited but enough to have an interesting generation result, without removing the role of the developer that would still have some logic to implement.
These modelers help in getting a vision closer to functional needs, Acceleo helps with the transformation of these models into useful stuff like documentation or software...