
## 4.2 Atl

The Atlas Transformation Language (ATL) allow us to define transformation rules according to one or several metamodels. The rules clearly state how concepts from source metamodels are matched to concepts of the target ones. Figure 10 shows some of the ATL
rules used to transform the concepts of the **Flat s-COMMA** metamodel to the concepts of the Gecode/J metamodel. The metamodel of Gecode/J is not presented here since it is very close to the **Flat sCOMMA** metamodel. Indeed, most CP solver languages are used to express quite the same concepts and **Flat s-COMMA** is designed to be as close as possible from the solving level. This is a great asset because transformation rules become simple: we mainly need one to one transformations.

1. module FlatsComma2GecodeJ; 2. create OUT : GecodeJ from IN : FlatsComma; 3.

4. rule Problem2Problem { 5. from 6. s : FlatsComma!Problem (
7. )
8. to 9. t : GecodeJ!Problem( 10. name <- s.name, 11. variables <- s.variables, 12. constraints <- s.constraints, 13. enumTypes <- s.enumTypes 14. )
15. } 16.

17. rule Variable2Variable {
18. from 19. s : FlatsComma!Variable ( 20. not s.isArrayVariable 21. )
22. to 23. t : GecodeJ!Variable ( 24. name <- s.name, 25. type <- s.type, 26. domain <- s.domain 27 )
28. }
29. 30. helper context FlatsComma!Variable def: 31. isArrayVariable : Boolean=
32. not self.array.oclIsUndefined();

![0_image_0.png](0_image_0.png)

The first line of this file specifies the name of the transformation.

A **module** is used to define and regroup a set of rules and helpers.

Rules define the mappings, and helpers allow to define factorized ATL code that can be called from different points of the ATL file
(they can be viewed as the ATL equivalent to Java methods).

Line 2 states the target (**create**) and source metamodels (**from**).

The first rule presented is called **Problem2Problem** and defines the matching between the concepts **Problem** expressed in **Flat sCOMMA** and Gecode/J. The source elements are stated with the reserved word **from** and the target ones with the reserved word to. These elements are declared like variables with a name (s,t) and a type corresponding to a class in a metamodel (**FlatsComma!Problem,**
GecodeJ!Problem). In the target part of the rule the name attribute of the **Flat s-COMMA** problem is assigned to the Gecode/J
name (**name <- s.name**), this is just an string assignment. However, the following two statement are assignments between concepts that are defined as **reference** in the metamodel. So, they need a specific rule to carry out the transformation. For instance, the **Flat s-COMMA** KM3 metamodel defines that the reference variables is composed by a set of **Variable** elements. Thus, the statement (**variables <- s.variables**) calls implicitly the rule Variable2Variable, which defines the match between each element of objects **Variable**. It can be highlighted that the ATL engine requires a unique name for each rule and a unique matching case:
from and to blocks. When several rules can be applied a guard (the boolean test in line 20) over the from statement must remove choice ambiguities.

The **Variable2Variable** rule matches three elements. The first two statements are simple string assignments and the last one is a reference assignment. Let us remark that a second rule to process array variables has been defined (but not presented here) which includes an additional statement for the array element. These two rules are distinguished according to complementary guards over the source block using the helper **isArrayVariable**. Guards act as filter on the source variable instances to process. The presented helper **isArrayVariable** applies on variable instances in **Flat sCOMMA** models and returns true when the instance contains an array element. ATL inherits from OCL [22] syntax and semantics; and most OCL functions and types are available within ATL.

Although the rules used here are not complex, ATL is able to perform more difficult rules. For instance, the most difficult rule we defined, was the transformation rule from **Flat s-COMMA** matrix containing sets, which must be unrolled in the ECLiPSe models
(since set matrix are not supported). This unroll process is carried out by defining a single set in ECLiPSefor each cell in the matrix.

The name of each single variable is composed by the name of the matrix, and the corresponding row and column index.

1. rule Problem2Problem {
2. from 3. s : FlatsComma!Problem ( 4. s.hasSetMatrix 5. )
6. to 7. t : ECLiPSe!Problem ( 8. name <- s.name, 9. constraints <- s.constraints, 10. enumTypes <- s.enumTypes 11. )
12. do {
13. t.variables <- s.variables->collect(e| 14. if e.isSetMatrix() then 15. thisModule.getMatrixCells(e)->collect(f| 16. thisModule.SetMatrixVariable2Variable(f.var,f.i,f.j)
17. ) 18. else 19. e 20. endif 21. )->flatten(); 22. }
23. }
24. 25. rule SetMatrixVariable2Variable(var : FlatsComma!Variable, 26. **i : Integer, j : Integer) {**
27. to 28. t : ECLiPSe!Variable( 29. name <- var.name + i.toString() + '_' + j.toString(),
30. type <- var.type, 31. domain <- var.domain, 32. )
33. do { 34. t; 35. } 36. }
Figure 11. ATL rules for decomposing matrix containing sets.

![0_image_1.png](0_image_1.png)

![0_image_2.png](0_image_2.png)

Figure 11 shows the rule **Problem2Problem** defined for ECLiPSe, this rule has a condition (line 4) to check whether set matrix are defined in the model. If the condition is true, name, **constraints**
and **enumTypes** are matched normally, but **variables** has a special procedure to decompose the set matrix.

This procedure begins at line 12 with a do block. In this block, the **collect** loop iterates over the variables. Then, each of these