ATL Transformations

ATL Helpers and Guards

Master helper functions and guard conditions to write more sophisticated ATL transformations.

In this tutorial, you’ll learn how to create attribute helpers, query helpers, and use guard conditions to selectively apply transformation rules.

You’ll discover how helpers encapsulate complex logic, making transformations more readable and maintainable.

25 mins Estimated Time

Section 1

Understanding Helpers

Helpers are reusable functions that encapsulate logic. There are two types: attribute helpers (defined with def:) and query helpers (standalone functions).

Attribute helpers extend model elements with computed properties, whilst query helpers provide utility functions.

Step 1

Create a metamodel with a simple class structure.

This metamodel defines Book and Author classes with basic attributes.

Library.ecore
1<?xml version="1.0" encoding="UTF-8"?>
2<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="Library" nsURI="http://www.example.org/library" nsPrefix="lib">
4 <eClassifiers xsi:type="ecore:EClass" name="Book">
5 <eStructuralFeatures xsi:type="ecore:EAttribute" name="title" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
6 <eStructuralFeatures xsi:type="ecore:EAttribute" name="isbn" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
7 <eStructuralFeatures xsi:type="ecore:EAttribute" name="yearPublished" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
8 <eStructuralFeatures xsi:type="ecore:EReference" name="author" eType="#//Author"/>
9 </eClassifiers>
10 <eClassifiers xsi:type="ecore:EClass" name="Author">
11 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
12 <eStructuralFeatures xsi:type="ecore:EAttribute" name="birthYear" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
13 </eClassifiers>
14</ecore:EPackage>

Step 2

Define an attribute helper to compute derived information.

The isClassic attribute helper determines if a book was published before 1950.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;

Step 3

Add a query helper for formatting.

Query helpers are standalone functions that can be called with any argument.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;
10
11-- Query helper: formats a year with century suffix
12helper def: formatYear(year : Integer) : String =
13 if year < 1900 then
14 year.toString() + ' (19th century)'
15 else
16 if year < 2000 then
17 year.toString() + ' (20th century)'
18 else
19 year.toString() + ' (21st century)'
20 endif
21 endif;

Step 4

Combine multiple helpers in one transformation.

Use both attribute and query helpers to build complex transformations.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;
10
11-- Attribute helper: gets formatted publication information
12helper context Library!Book def: publicationInfo(): String =
13 thisModule.formatYear(self.yearPublished) + ' by ' + self.author.name;
14
15-- Query helper: formats a year with century suffix
16helper def: formatYear(year : Integer) : String =
17 if year < 1900 then
18 year.toString() + ' (19th century)'
19 else
20 if year < 2000 then
21 year.toString() + ' (20th century)'
22 else
23 year.toString() + ' (21st century)'
24 endif
25 endif;

Section 2

Using Guard Conditions

Guard conditions filter which source elements a rule applies to. They enable selective transformation based on element properties.

Guards use OCL boolean expressions in parentheses after the source element declaration.

Step 1

Add a simple guard condition.

This rule only transforms books published after 1950.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Rule with simple guard: only modern books
8rule ModernBook {
9 from
10 s: Library!Book (s.yearPublished >= 1950)
11 to
12 t: Catalog!Item (
13 title <- s.title,
14 category <- 'Modern'
15 )
16}

Step 2

Use helpers in guard conditions.

Guard conditions can call attribute helpers, combining reusable logic with selective application.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;
10
11-- Rule using helper in guard: only classic books
12rule ClassicBook {
13 from
14 s: Library!Book (s.isClassic())
15 to
16 t: Catalog!Item (
17 title <- s.title,
18 category <- 'Classic'
19 )
20}

Step 3

Create multiple rules with different guards.

Different rules handle different subsets of source elements based on their guards.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;
10
11-- Rule 1: Classic books
12rule ClassicBook {
13 from
14 s: Library!Book (s.isClassic())
15 to
16 t: Catalog!Item (
17 title <- s.title,
18 category <- 'Classic'
19 )
20}
21
22-- Rule 2: Modern books
23rule ModernBook {
24 from
25 s: Library!Book (not s.isClassic())
26 to
27 t: Catalog!Item (
28 title <- s.title,
29 category <- 'Modern'
30 )
31}

Step 4

Build a complete transformation with helpers and guards.

The complete transformation demonstrates how helpers and guards work together to create sophisticated model transformations.

LibraryTransform.atl
1-- @path Library=/Library/Library.ecore
2-- @path Catalog=/Catalog/Catalog.ecore
3
4module LibraryTransform;
5create OUT: Catalog from IN: Library;
6
7-- Attribute helper: determines if a book is a classic
8helper context Library!Book def: isClassic(): Boolean =
9 self.yearPublished < 1950;
10
11-- Attribute helper: gets formatted publication information
12helper context Library!Book def: publicationInfo(): String =
13 thisModule.formatYear(self.yearPublished) + ' by ' + self.author.name;
14
15-- Query helper: formats a year with century suffix
16helper def: formatYear(year : Integer) : String =
17 if year < 1900 then
18 year.toString() + ' (19th century)'
19 else
20 if year < 2000 then
21 year.toString() + ' (20th century)'
22 else
23 year.toString() + ' (21st century)'
24 endif
25 endif;
26
27-- Rule 1: Classic books with detailed information
28rule ClassicBook {
29 from
30 s: Library!Book (s.isClassic())
31 to
32 t: Catalog!Item (
33 title <- s.title,
34 category <- 'Classic',
35 description <- 'Published ' + s.publicationInfo()
36 )
37}
38
39-- Rule 2: Modern books with standard information
40rule ModernBook {
41 from
42 s: Library!Book (not s.isClassic())
43 to
44 t: Catalog!Item (
45 title <- s.title,
46 category <- 'Modern',
47 description <- 'Published ' + s.publicationInfo()
48 )
49}

Check Your Understanding

Question 1 of 3

What is the difference between attribute helpers and query helpers?

Question 2 of 3

When are guard conditions evaluated?

Question 3 of 3

Can a helper call another helper?

Working with Collections

Learn how to manipulate collections in ATL transformations using OCL collection operations.