Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Acceleo/User Guide"

(Acceleo Projects)
(Creation of an Acceleo project)
Line 327: Line 327:
  
 
These example are really useful to start with Acceleo, so don't hesitate to import them, examine them, and modify them!
 
These example are really useful to start with Acceleo, so don't hesitate to import them, examine them, and modify them!
 +
 +
 +
===Creating An Acceleo UI Project===
 +
 +
 +
 +
 +
 +
 +
 +
This action can only be performed on an existing Acceleo project.
 +
 +
It allows you to create and initialize a plug-in project that will contain everything needed to launch the Acceleo generations of your project through actions available in pop-up menus, integrated in eclipse. This facilitates a lot the deployment of Acceleo generators in the eclipse platform. The created UI plug-in project is configured to create a popup menu on files with a given extension and to generate files in a folder found by evaluating a java expression, which can be customized.
 +
 +
To perform this, just right-click on your Acceleo project, then select '''Acceleo > Create Acceleo UI Launcher Project'''.
 +
 +
 +
 +
This will start a wizard that will guide you through the creation process. First, enter the target UI plug-in project name.
 +
 +
 +
Then, select the projects this UI plug-in will depend on. In our example, we only depend on our Acceleo generator project, but in real life, an UI project could require several Acceleo projects, plus optionally other projects depending on your working environment.
 +
 +
 +
 +
The wizard now requires the following information:
 +
 +
* The generator name (this name will be displayed to users in the UI);
 +
* The model filename filter, which indicates on which file extensions the popup menu will appear;
 +
* The java code that is responsible to find the target folder and assign it to a target variable of type '''IContainer'''. By default, the wizard proposes some code which uses the '''src-gen''' folder in the project that contains the model chosen by the user.
 +
 +
 +
Click on '''Finish'''.
 +
 +
A new plug-in project is then created in the workspace with the previously entered information. This plug-in can be maintained as any other plug-in project in Eclipse.
 +
 +
 +
 +
To see this plug-in in action, just open the plug-in's '''MANIFEST.MF''', and click on the '''Launch an Eclipse application''' link in the '''Testing''' paragraph.
 +
 +
 +
 +
A new action appears in the pop-up menu when right-clicking on files whose name matches the name filter declared in the extension described in the '''plugin.xml''' file of the UI plug-in.
 +
 +
 +
 +
By default, the generated UI plug-in matches any file.
 +
 +
The menu where the generation action appears and everything else can be adapted to your needs via the eclipse extension mechanism. For example, the name filter for which this action will be proposed can be modified like this:
 +
 +
* Open the '''MANIFEST.MF''' file;
 +
* Go to the '''Extensions''' tab;
 +
* Modify the '''nameFilter''' field of the '''popupMenus''' extension.
 +
 +
 +
For more information about the Eclipse extension mechanism, please refer to the eclipse '''Plug-in Development Environment (PDE)''' documentation.

Revision as of 07:24, 21 February 2018

Installing Acceleo

Acceleo can be downloaded and installed in a number of ways. If you have an existing Eclipse installation and simply wish to install Acceleo in it, Installing through the update site is the easiest way. If you'd rather install a new Eclipse with Acceleo, you may want to take a look at the facilities provided by the amalgamation project.

For those of you that need to retrieve the zips of Acceleo, you can either look at the latest releases or the legacy releases if you need one of the 2.x releases.

Note: Whatever the installation procedure you choose, examples are available from the menu right-click => New => Examples => Acceleo Plug-ins.

The Acceleo language

Acceleo 3 is an implementation of the MOFM2T specification defined by the OMG. The Acceleo language, named as MTL by the OMG, is composed of two main types of structures (templates and queries) inside of a module. In Acceleo, you can create expressions using a subset of OCL in order query the input models.

Modules

An Acceleo module is a ".mtl" file, which contains templates (to generate code) and/or queries (to extract information from the manipulated models). The file must start with the module declaration in the form:

[module <module_name>('metamodel_URI_1', 'metamodel_URI_2')]

A module can extend another module, in which case its templates will be able to override its parent's "public" and "protected" templates. It will also have access to its parent's public and protected templates and queries. A module can also import another module to access its public templates and queries.

Import

An Acceleo module generally depends on other modules for its execution. Consequently, Acceleo modules explicitly declare the modules they depend on via import declarations.

The syntax is the following:

import qualified::name::of::imported::module

The content assistant (Ctrl + Space) will propose you all accessible modules. Select the module you want to import and its qualified name will be inserted.

Note: It is possible to use a non-qualified name in an import, but this is not recommended since it can easily lead to bugs that are hard to understand in case of name conflicts between Acceleo modules.

The content assistant can be invoked to generate an import tag: just enter import, then Ctrl + Space, and the completion proposes "import" and generates an [import... /] tag.

Static Overriding

Acceleo allows you to override a part of the behavior of another module by extending it and by overriding some of its templates (all templates except those without with a private visibility). It can be very useful to re-use some common part of a module and to create common parents to several modules just like in object oriented programming.

Templates

Templates are sets of Acceleo statements used to generate text. They are delimited by [template...][/template] tags.

To create a new template, just place the cursor in an Acceleo module file at a relevant position (i.e. one where it is possible to insert a template!) and hit Ctrl + Space. The content assistant proposes, among other things, to create a new template. It's also possible to type template, Ctrl + Space, then Return, and a new template is created:

You can fill-in its name, parameter name, and parameter type. Just hit Tab to pass from an element to the next.

Templates can also have optional elements:

  • Overriding (which will be detailed in The Overrides View);
  • Pre-conditions (or guard conditions);
  • Post-treatments;
  • Variable initializations.

Once again, the content assistant can help you here. just hit Ctrl + Space before the final ] of your template declaration, and see what it proposes.

Pre-Conditions

Imagine you want to implement different behavior for a template depending on certain conditions.

One way to do that would be to use if blocks to distinguish between those cases. Another, more elegant, way is to use pre-conditions. Let's say that you want to generate different code for associations whether or not they are declared ordered.

The above example shows the ? (condition) syntax that tells Acceleo that the template must only be run if the pre-condition is satisfied.


Note:

  • The order of declaration of templates in a module is important: The first template for which the guard condition evaluates to true will be executed. No guard condition on a template is exactly equivalent to ? (true).
  • Pre-conditions also exist on for blocks.


Post-Treatments

It is often useful, especially for code formatting, to apply certain treatments on the text generated by a template before actually writing it to the output file.

For instance, trimming the result of a template is really very useful to make sure of your formatting while keeping a readable formatting for your templates.

Let's see an example to make things clear:

In the above example, without the post-treatment post (trim()), the template invocation would write the name followed by a carriage return. With the post-treatment, whenever the template is called, it will just write the expected name, without a carriage return, which is probably what you need.

The most common uses of post-treatments is output code formatting, thanks to post (trim()). It's up to you to figure out what else you will use it for!

Variable Initialization

Templates (and other blocks as well) can define some variables and initialize them directly in their main syntactic block.

You can declare 0, 1, or several variables. If you declare several variables, it may be opportune to format the template this way:

Note: Variable initilization also exists on for blocks.

Queries

Queries are used to extract information from the model. Queries return values, or collections of values. They use OCL, enclosed in a [query ... /] tag.

Queries are specified to always return the same value each time they are invoked with the same arguments.

Wrapping Java Services

It is sometimes useful to invoke some java code from inside an Acceleo template. The acceleo non-standard library provides a service invoke which allows just that. The invoked java service can be wrapped in an Acceleo query.

To facilitate the creation of such a wrapper, proceed like this: 1- Right-click on the package you want to create your Acceleo module in, and select New > Acceleo Module File 2- In the wizard, enter the relevant information in the usual fields, then click on the Advanced >> button 3- Check the Initialize Content checkbox 4- Select Create a Java services wrapper in the listbox below 5- Select the java file that contains the services to wrap 6- Click on the Finish button

That's it!

An Acceleo module is created, with a query for each service found in the original java class.

Language Elements

File Tags

File tags are used to tell the Acceleo engine it must generate the content of the [file ...] tag in an actual file.

The syntax is the following:

[file(<uri_expression>, <append_mode>, <output_encoding>)] (...) [/file]

  • <uri_expression> denotes the output file name;
  • <append_mode> (optional) indicates whether the output text must be appended to the file or replace its content;
  • <output_encoding> (optional) indicates the encoding to use for the output file. This encoding need not be the same as the module's encoding.

Note: A template that contains a [file] tag does not necessarily have an annotation @main. @main annotations are used to indicate to the Acceleo eclipse plug-in that a java class must be generated to encapsulate the code required to run a generation. @main annotations can be placed on templates which have no [file] tag, but such templates must eventually call one or more templates that do have [file] tags if you want to get a result!

Please refer to the official MTL Specification for more details.

For Loops

For loops in Acceleo can be expressed with two syntaxes:

  • The full syntax (conformant with the MTL specification): [for (i : E | e)]...[/for]
  • The light syntax: [for (<iterable_expression>)]...[/for]

Note: When using the light syntax, an implicit variable i is created, which contains the index of current iteration, starting at 1.

Content assistant can be very helpful to make sure you use the right syntax. For example, imagine that you want to insert a for loop, but you don't remember for sure the Acceleo syntax for these loops.

Just type for in the editor, then Ctrl + Space. Acceleo proposes the for loop to be automatically inserted.

Hit Return to confirm that you actually want to insert a for loop:


You can now enter:

  • The iterator variable name;
  • The iterator type;
  • The iterable expression.


Just hit the Tab key to jump from one element to the next, as usual with eclipse code templates.

Here is an example of a for loop to generate some code for each attribute of a UML class:


Finally, it is useful to know that it is possible to specify behavior to be run before, between, or after each iteration of a for loop.

The content assistant proposes the corresponding options when invoked in the declaration of a for loop, as can be seen on the picture below.


The syntactic structure are respectively before(), separator()<c/ode>, and <code>after().

Example:

[for (Sequence{1, 2, 3}) before ('sequence: ') separator (', ') after (';')][self/][/for]

Will generate the following text:

sequence: 1, 2, 3;

If Conditions

If conditions are written like this: [if (condition)]...[/if]

You can enter if, hit Ctrl + Space, then Return, and the Acceleo editor will insert the right syntax so you just have to enter the condition expression.

And that's all there is to it!

Let Blocks

It is important to understand that variables in Acceleo are final, which means that their value cannot be changed after they have been initialized.

Please also note that the Acceleo let hasn't got the same semantics nor the same behavior as the OCL let

The syntax is the following: [let (variableName : VariableType = expression)]...[/let]

Where variableName is the variable's name and VariableType the variable's type, and expression is an expression which value will be assigned to the variable if its type corresponds (Acceleo let blocks are equivalent to if (expression.oclIsKindOf(VariableType)).

Variables only exist inside of a let block. Their lifetime consequently cannot exceed that of their template. They are only visible inside of the let block, which means that templates called within this block cannot "see" them. If you need a sub-template to access a variable, you have to pass it as an argument.

Variables are especially useful to store a value and prevent computing it several times in a row.

You can enter let, hit Ctrl + Space, then Return, and the Acceleo editor will insert the right syntax so you just have to enter the variable name and type.


Comments

Comments are entered in [comment/] blocks, and appear in some shade of green. The [comment/] tag can be self closed:

[comment Here is some comment of utter importance/]

But you can also surround a block of text between comment tags:

[comment]Here is some commented text, which cannot contain a right bracket character.[/comment]

Such comments are part of the official MTL specification. They cannot be placed inside OCL code, such as queries for instance. They cannot be placed in the middle of an Acceleo statement either.

It is possible to comment some portion of code or text of an Acceleo module with the Ctrl + / shortcut, or by right-clicking on the selected text and then Source > Comment.

The behavior depends on what is selected:

  • If nothing is selected, the current line (not the line you right-clicked on, but the line where the cursor is located) is surrounded with [comment]...[/comment] tags.
  • If some text is selected, it is surrounded with [comment]...[/comment]tags, whether it spans multiple lines or not.

Main Modules and Launcher class

"Main" Acceleo modules are entry points, that is to say modules which are used to describe, in some way, the generation workflow.

Such modules can be created from standard acceleo modules, they just have to contain the @main annotation.

They do not necessary have to contain [file] tags: Main modules are the executable modules, they need not be modules that actually generate files.

Nevertheless, Acceleo proposes a facility to create main modules. Right-click in the package explorer, if possible on the package in which you want to create a new main module though this is not necessary. Select New > Other... (or Ctrl + N). Select Acceleo Main Module File in the acceleo Model to Text category.


Click on Next >. Enter the name of the module to create (without the .mtl extension) and the folder in which it must be created, if the proposed folder is inconvenient.


Click on Next >. Select the templates that this main module will call to actually generate files.


Click on Finish. A new Acceleo module is created, which contains the @main annotation and consequently has a generated java file attached. This module imports the modules that have been selected in the preceding wizard page, and just calls them one after the other.


You can now freely edit the content of this module to implement the workflow you need. The created file is just an accelerator to initialize this task. It will be sufficient in most cases but can be modified at will.


Behavior

The main template will be called on all the elements of the model with the given type. The beginning of the execution of the main template initialized the generation. As such, if you have a main template defined on a UML Class, this template will be called for all your classes but it also mean that the generator will be initialized for each call to this main template so, for example, the cache of the queries will be cleared after each call. It is recommended to define the main module on the root of your metamodel and then to navigate manually in your model to call all the other templates. On a UML model, you would improve performances by defining your generator on the root concept Model instead of Class.


Creation of an Acceleo project

Acceleo Projects

Acceleo projects are eclipse projects associated with the Acceleo nature. Such projects contain Acceleo modules, java code, and anything required for the needs of the code generation to achieve.

Note: It is recommended to use a naming that respects the eclipse plug-ins naming conventions. Of course, the name prefix has to be adapted to your specific context, but remember that using a naming convention that prevents naming conflicts is a good idea.


Creating An Acceleo Project "From Scratch"

The aim of an Acceleo project is to generate text from a model (or from a set of models). For this tutorial, we will create a new Acceleo module for generating java beans from a UML model.


To create a new Acceleo project, right click on the package explorer view then select New->Acceleo Project.


Choose a correct plug-in name for the project, then click on next.

This wizard page allows you to initialize the project by creating one or several Acceleo module files.

Select the folder in which you want to create the new module file.

Fill in the module name

Optionally, you can select an existing file which will be copied into the new module file. This could be useful to create a module from an existing "target" file.

Then, select the metamodel from which your generation file will take its types (in this example, UML)

Finally, choose the metaclass that will be used to generate the file (in this example, Class). This can be modified later at any time directly in the module files.

Note: Other options are available to initialize the new module with existing content. These options will be discussed later.


You can create more than one module file in this project by using the Add button on the left.

Clicking on Finish will create the module file(s), and some files automatically generated from it (more on these below).



Transforming An Existing Project Into An Acceleo Project

Acceleo provides a facility to convert an existing project into an Acceleo project. Technically, this means that the Acceleo nature will be added to the project's natures.

This can be achieved by right-clicking in the package explorer, then selecting New > Convert to an Acceleo Project.


Select the project(s) that must be turned into Acceleo project(s), and click on Finish.


Note: The Acceleo nature can be removed from an Acceleo project simply by right-clicking on the project and selecting Acceleo > Remove Acceleo Nature.




Installing An Example Acceleo Project

Acceleo provides several example projects which you can use to get started and take a look at how to organize generator projects.

To install one of these examples in your workspace, right-click in the package explorer and select New > Other.... Go to the Examples folder, then to Acceleo Plug-ins and select the example to import into your workspace. Each example has a small description displayed at the top of the window.


Click on Finish, and one or several new projects appear in your workspace.

These example are really useful to start with Acceleo, so don't hesitate to import them, examine them, and modify them!


Creating An Acceleo UI Project

This action can only be performed on an existing Acceleo project.

It allows you to create and initialize a plug-in project that will contain everything needed to launch the Acceleo generations of your project through actions available in pop-up menus, integrated in eclipse. This facilitates a lot the deployment of Acceleo generators in the eclipse platform. The created UI plug-in project is configured to create a popup menu on files with a given extension and to generate files in a folder found by evaluating a java expression, which can be customized.

To perform this, just right-click on your Acceleo project, then select Acceleo > Create Acceleo UI Launcher Project.


This will start a wizard that will guide you through the creation process. First, enter the target UI plug-in project name.


Then, select the projects this UI plug-in will depend on. In our example, we only depend on our Acceleo generator project, but in real life, an UI project could require several Acceleo projects, plus optionally other projects depending on your working environment.


The wizard now requires the following information:

  • The generator name (this name will be displayed to users in the UI);
  • The model filename filter, which indicates on which file extensions the popup menu will appear;
  • The java code that is responsible to find the target folder and assign it to a target variable of type IContainer. By default, the wizard proposes some code which uses the src-gen folder in the project that contains the model chosen by the user.


Click on Finish.

A new plug-in project is then created in the workspace with the previously entered information. This plug-in can be maintained as any other plug-in project in Eclipse.


To see this plug-in in action, just open the plug-in's MANIFEST.MF, and click on the Launch an Eclipse application link in the Testing paragraph.


A new action appears in the pop-up menu when right-clicking on files whose name matches the name filter declared in the extension described in the plugin.xml file of the UI plug-in.


By default, the generated UI plug-in matches any file.

The menu where the generation action appears and everything else can be adapted to your needs via the eclipse extension mechanism. For example, the name filter for which this action will be proposed can be modified like this:

  • Open the MANIFEST.MF file;
  • Go to the Extensions tab;
  • Modify the nameFilter field of the popupMenus extension.


For more information about the Eclipse extension mechanism, please refer to the eclipse Plug-in Development Environment (PDE) documentation.

Back to the top