AQL Query Language

AQL Basics

Learn the fundamentals of the Acceleo Query Language (AQL) for navigating and querying models.

In this tutorial, you’ll explore AQL syntax, basic navigation operations, literal values, and simple expressions. AQL is the query language used throughout the Swift Modelling framework for model navigation in both ATL transformations and MTL templates.

20 mins Estimated Time

Section 1

Understanding AQL

AQL (Acceleo Query Language) is an expression language for navigating and querying models. It provides a concise syntax for accessing model elements, their properties, and relationships.

AQL expressions are used extensively in ATL transformations and MTL templates to navigate model structures and extract information.

AQL Model Navigation

Step 1

Create a simple metamodel for testing AQL queries.

This metamodel defines a Company with Employees. Each Employee has a name, age, and department. We’ll use this to explore AQL navigation.

Company.ecore
1<?xml version="1.0" encoding="UTF-8"?>
2<ecore:EPackage xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
5 name="company" nsURI="http://www.example.org/company" nsPrefix="company">
6
7 <!-- Company: root container for the organisation -->
8 <eClassifiers xsi:type="ecore:EClass" name="Company">
9 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
10 <eStructuralFeatures xsi:type="ecore:EAttribute" name="founded" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
11 <eStructuralFeatures xsi:type="ecore:EReference" name="departments" upperBound="-1"
12 eType="#//Department" containment="true"/>
13 </eClassifiers>
14
15 <!-- Department: organisational unit within the company -->
16 <eClassifiers xsi:type="ecore:EClass" name="Department">
17 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
18 <eStructuralFeatures xsi:type="ecore:EAttribute" name="budget" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"/>
19 <eStructuralFeatures xsi:type="ecore:EReference" name="employees" upperBound="-1"
20 eType="#//Employee" containment="true"/>
21 <eStructuralFeatures xsi:type="ecore:EReference" name="manager" eType="#//Employee"/>
22 </eClassifiers>
23
24 <!-- Employee: worker within a department -->
25 <eClassifiers xsi:type="ecore:EClass" name="Employee">
26 <eStructuralFeatures xsi:type="ecore:EAttribute" name="name" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
27 <eStructuralFeatures xsi:type="ecore:EAttribute" name="salary" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EDouble"/>
28 <eStructuralFeatures xsi:type="ecore:EAttribute" name="age" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EInt"/>
29 <eStructuralFeatures xsi:type="ecore:EAttribute" name="title" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
30 <eStructuralFeatures xsi:type="ecore:EAttribute" name="department" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/>
31 <eStructuralFeatures xsi:type="ecore:EReference" name="supervisor" eType="#//Employee"/>
32 </eClassifiers>
33</ecore:EPackage>

Step 2

Create a model instance to query.

This model instance contains a company with several employees in different departments. We’ll query this data using AQL expressions.

company-instance.xmi
1<?xml version="1.0" encoding="UTF-8"?>
2<xmi:XMI xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
3 xmlns:company="http://www.example.org/company">
4
5 <company:Company name="Acme Corp" founded="1995">
6 <departments name="Engineering" budget="500000.0" manager="//@departments.0/@employees.0">
7 <employees name="Alice Smith" salary="120000.0" age="35" title="Engineering Director" department="Engineering"/>
8 <employees name="Bob Chen" salary="95000.0" age="28" title="Senior Developer" department="Engineering" supervisor="//@departments.0/@employees.0"/>
9 <employees name="Carol Williams" salary="85000.0" age="32" title="Developer" department="Engineering" supervisor="//@departments.0/@employees.1"/>
10 <employees name="David Lee" salary="75000.0" age="25" title="Junior Developer" department="Engineering" supervisor="//@departments.0/@employees.1"/>
11 </departments>
12 <departments name="Marketing" budget="300000.0" manager="//@departments.1/@employees.0">
13 <employees name="Emma Davis" salary="110000.0" age="40" title="Marketing Director" department="Marketing"/>
14 <employees name="Frank Miller" salary="80000.0" age="30" title="Marketing Manager" department="Marketing" supervisor="//@departments.1/@employees.0"/>
15 <employees name="Grace Kim" salary="65000.0" age="26" title="Marketing Specialist" department="Marketing" supervisor="//@departments.1/@employees.1"/>
16 </departments>
17 <departments name="Finance" budget="200000.0" manager="//@departments.2/@employees.0">
18 <employees name="Henry Brown" salary="115000.0" age="45" title="Finance Director" department="Finance"/>
19 <employees name="Ivy Chen" salary="90000.0" age="33" title="Senior Accountant" department="Finance" supervisor="//@departments.2/@employees.0"/>
20 </departments>
21 </company:Company>
22</xmi:XMI>

Step 3

Test basic property access.

The simplest AQL expressions access properties directly. Use dot notation to navigate from objects to their attributes and references.

Terminal
1# Property Access - Reading simple attribute values
2# Access properties using dot notation
3
4# Get the company name
5swift-aql evaluate --model company-data.xmi \
6 --expression "company.name"
7
8# Output: "Acme Corp"
9
10# Get the founding year
11swift-aql evaluate --model company-data.xmi \
12 --expression "company.founded"
13
14# Output: 1995
15
16# Get a department's budget
17swift-aql evaluate --model company-data.xmi \
18 --expression "company.departments->first().budget"
19
20# Output: 500000.0
21
22# Get an employee's salary
23swift-aql evaluate --model company-data.xmi \
24 --expression "company.departments->first().employees->first().salary"
25
26# Output: 120000.0

Step 4

Use literal values and operations.

AQL supports various literal types: strings (‘text’), integers (42), booleans (true/false), and real numbers (3.14). You can combine these with basic operations.

Terminal
1# Literals - Using constant values in expressions
2# AQL supports various literal types
3
4# String literals
5swift-aql evaluate --model company-data.xmi \
6 --expression "'Hello, World!'"
7
8# Output: "Hello, World!"
9
10# Integer literals
11swift-aql evaluate --model company-data.xmi \
12 --expression "42"
13
14# Output: 42
15
16# Real (floating point) literals
17swift-aql evaluate --model company-data.xmi \
18 --expression "3.14159"
19
20# Output: 3.14159
21
22# Boolean literals
23swift-aql evaluate --model company-data.xmi \
24 --expression "true"
25
26# Output: true
27
28# Null literal
29swift-aql evaluate --model company-data.xmi \
30 --expression "null"
31
32# Output: null
33
34# Comparing with literals
35swift-aql evaluate --model company-data.xmi \
36 --expression "company.founded = 1995"
37
38# Output: true

Section 3

Basic Operations and Comparisons

AQL supports arithmetic operations, string manipulation, and comparison operators. These form the foundation for more complex queries and filtering operations.

Operations work with both literal values and model properties, allowing you to perform calculations and comparisons directly in your queries.

Step 1

Perform arithmetic operations.

AQL supports standard arithmetic: addition (+), subtraction (-), multiplication (*), division (/), and modulo (%). Operations follow standard precedence rules.

Terminal
1# Arithmetic Operations - Mathematical calculations
2# Perform calculations on numeric values
3
4# Basic arithmetic
5swift-aql evaluate --model company-data.xmi \
6 --expression "10 + 5"
7
8# Output: 15
9
10swift-aql evaluate --model company-data.xmi \
11 --expression "100 - 35"
12
13# Output: 65
14
15swift-aql evaluate --model company-data.xmi \
16 --expression "12 * 8"
17
18# Output: 96
19
20swift-aql evaluate --model company-data.xmi \
21 --expression "100 / 4"
22
23# Output: 25
24
25# Modulo (remainder)
26swift-aql evaluate --model company-data.xmi \
27 --expression "17.mod(5)"
28
29# Output: 2
30
31# Calculations with model values
32swift-aql evaluate --model company-data.xmi \
33 --expression "company.departments->first().budget / 12"
34
35# Output: 41666.67 (monthly budget)
36
37# Calculate average salary
38swift-aql evaluate --model company-data.xmi \
39 --expression "let salaries = company.departments.employees.salary
40 in salaries->sum() / salaries->size()"
41
42# Output: 92777.78 (approximate average)
43
44# Percentage calculation
45swift-aql evaluate --model company-data.xmi \
46 --expression "let eng = company.departments->first()
47 in eng.employees.salary->sum() / eng.budget * 100"
48
49# Output: 75.0 (salary as percentage of budget)

Step 2

Work with string operations.

String operations include concatenation (+), size calculation, and case conversion. These are essential for text processing and code generation.

Terminal
1# String Operations - Manipulating text values
2# Common string manipulation functions
3
4# String concatenation
5swift-aql evaluate --model company-data.xmi \
6 --expression "'Hello' + ' ' + 'World'"
7
8# Output: "Hello World"
9
10# Concatenate with model values
11swift-aql evaluate --model company-data.xmi \
12 --expression "company.name + ' (founded ' + company.founded.toString() + ')'"
13
14# Output: "Acme Corp (founded 1995)"
15
16# String length
17swift-aql evaluate --model company-data.xmi \
18 --expression "company.name.size()"
19
20# Output: 9
21
22# Substring
23swift-aql evaluate --model company-data.xmi \
24 --expression "'Engineering'.substring(1, 4)"
25
26# Output: "Eng"
27
28# Case conversion
29swift-aql evaluate --model company-data.xmi \
30 --expression "company.name.toUpper()"
31
32# Output: "ACME CORP"
33
34swift-aql evaluate --model company-data.xmi \
35 --expression "company.name.toLower()"
36
37# Output: "acme corp"
38
39# String contains
40swift-aql evaluate --model company-data.xmi \
41 --expression "company.departments->first().name.contains('Engineer')"
42
43# Output: true
44
45# String starts/ends with
46swift-aql evaluate --model company-data.xmi \
47 --expression "company.departments.name->select(n | n.endsWith('ing'))"
48
49# Output: ["Engineering", "Marketing"]

Step 3

Use comparison operators.

Comparison operations (=, <>, <, >, <=, >=) return boolean values. These form the basis for filtering and conditional logic in more complex queries.

Terminal
1# Comparison Operations - Testing relationships between values
2# Use comparisons for filtering and conditions
3
4# Equality
5swift-aql evaluate --model company-data.xmi \
6 --expression "company.name = 'Acme Corp'"
7
8# Output: true
9
10# Inequality
11swift-aql evaluate --model company-data.xmi \
12 --expression "company.founded <> 2000"
13
14# Output: true
15
16# Less than / Greater than
17swift-aql evaluate --model company-data.xmi \
18 --expression "company.departments.employees->select(e | e.salary > 100000)->collect(e | e.name)"
19
20# Output: ["Alice Smith", "Emma Davis", "Henry Brown"]
21
22swift-aql evaluate --model company-data.xmi \
23 --expression "company.departments.employees->select(e | e.age < 30)->collect(e | e.name)"
24
25# Output: ["Bob Chen", "David Lee", "Grace Kim"]
26
27# Less than or equal / Greater than or equal
28swift-aql evaluate --model company-data.xmi \
29 --expression "company.departments->select(d | d.budget >= 300000)->collect(d | d.name)"
30
31# Output: ["Engineering", "Marketing"]
32
33# Boolean operators: and, or, not
34swift-aql evaluate --model company-data.xmi \
35 --expression "company.departments.employees
36 ->select(e | e.salary > 80000 and e.age < 35)
37 ->collect(e | e.name)"
38
39# Output: ["Bob Chen", "Ivy Chen"]
40
41swift-aql evaluate --model company-data.xmi \
42 --expression "company.departments.employees
43 ->select(e | e.salary > 110000 or e.age > 40)
44 ->collect(e | e.name)"
45
46# Output: ["Alice Smith", "Henry Brown", "Emma Davis"]

Step 4

Combine operations in expressions.

Complex expressions combine multiple operations, navigation steps, and function calls. Use parentheses to control evaluation order when needed.

Terminal
1# Combined Expressions - Putting it all together
2# Build complex queries using multiple operations
3
4# Generate employee report string
5swift-aql evaluate --model company-data.xmi \
6 --expression "company.departments.employees
7 ->collect(e | e.name + ' (' + e.title + '): $' + e.salary.toString())"
8
9# Output: ["Alice Smith (Engineering Director): $120000.0", ...]
10
11# Calculate department statistics
12swift-aql evaluate --model company-data.xmi \
13 --expression "company.departments->collect(d |
14 d.name + ': ' + d.employees->size().toString() + ' employees, ' +
15 'avg salary $' + (d.employees.salary->sum() / d.employees->size()).toString())"
16
17# Output: ["Engineering: 4 employees, avg salary $93750.0", ...]
18
19# Find highest paid employee per department
20swift-aql evaluate --model company-data.xmi \
21 --expression "company.departments->collect(d |
22 let maxSalary = d.employees.salary->max() in
23 d.name + ': ' + d.employees->select(e | e.salary = maxSalary)->first().name)"
24
25# Output: ["Engineering: Alice Smith", "Marketing: Emma Davis", "Finance: Henry Brown"]
26
27# Complex filtering with aggregation
28swift-aql evaluate --model company-data.xmi \
29 --expression "let seniorEmployees = company.departments.employees
30 ->select(e | e.age >= 30 and e.salary >= 80000)
31 in 'Senior employees: ' + seniorEmployees->size().toString() +
32 ', Total salary: $' + seniorEmployees.salary->sum().toString()"
33
34# Output: "Senior employees: 6, Total salary: $595000.0"
35
36# Conditional report generation
37swift-aql evaluate --model company-data.xmi \
38 --expression "company.departments->collect(d |
39 d.name + ' is ' +
40 if d.budget >= 400000 then 'high budget'
41 else if d.budget >= 250000 then 'medium budget'
42 else 'low budget' endif endif)"
43
44# Output: ["Engineering is high budget", "Marketing is medium budget", "Finance is low budget"]

Check Your Understanding

Question 1 of 3

What does the AQL expression employee.name return?

Question 2 of 3

How do you safely navigate through a reference that might be null?

Question 3 of 3

What is the result of the AQL expression 'Hello' + ' ' + 'World'?

Filtering and Selection

Master AQL’s powerful filtering and selection operations to extract specific elements from collections.