Article
Understanding AQL
Learn the fundamental concepts of the Acceleo Query Language.
Overview
AQL (Acceleo Query Language) (https://eclipse.dev/acceleo/documentation/) is an expression language designed for querying models. It provides a concise syntax for navigating model structures, filtering collections, and computing values.
AQL is based on OMG OCL (Object Constraint Language) (https://www.omg.org/spec/OCL/) semantics but with a simplified, more accessible syntax.
Expression Types
Literals
AQL supports various literal types:
'Hello' -- String
42 -- Integer
3.14 -- Real/Double
true -- Boolean
false -- Boolean
null -- Null value
Variables
Access variables defined in the context:
self -- The current context object
myVariable -- A named variable
Navigation
Navigate model structures using dot notation:
self.name -- Attribute access
self.package -- Single reference
self.attributes -- Collection reference
self.package.name -- Chained navigation
self.package.classes.name -- Navigation through collections
Operation Calls
Call operations on values:
self.name.toUpper() -- Instance operation
self.attributes->size() -- Collection operation
self.name.substring(0, 5) -- Operation with arguments
Collection Operations
Collections are central to AQL. Operations use the -> arrow syntax.
Basic Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Number of elements |
|
|
|
True if no elements |
|
|
|
True if has elements |
|
|
|
First element |
|
|
|
Last element |
|
|
|
Element at index |
|
Filtering
|
Operation |
Description |
Example |
|---|---|---|
|
|
Keep matching elements |
|
|
|
Remove matching elements |
|
Transformation
|
Operation |
Description |
Example |
|---|---|---|
|
|
Map to new values |
|
|
|
Flatten nested collections |
|
Testing
|
Operation |
Description |
Example |
|---|---|---|
|
|
All elements match |
|
|
|
Any element matches |
|
|
|
Exactly one matches |
|
|
|
Contains element |
|
|
|
Doesn’t contain |
|
Set Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Combine collections |
|
|
|
Common elements |
|
|
|
Remove specific element |
|
|
|
Add element |
|
Aggregation
|
Operation |
Description |
Example |
|---|---|---|
|
|
Sum of numbers |
|
|
|
Minimum value |
|
|
|
Maximum value |
|
String Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Uppercase |
|
|
|
Lowercase |
|
|
|
Concatenate |
|
|
|
Extract portion |
|
|
|
Length |
|
|
|
Check prefix |
|
|
|
Check suffix |
|
|
|
Contains substring |
|
|
|
Replace all |
|
|
|
Remove whitespace |
|
Boolean Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Logical AND |
|
|
|
Logical OR |
|
|
|
Logical NOT |
|
|
|
Implication |
|
Comparison Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Equal |
|
|
|
Not equal |
|
|
|
Less than |
|
|
|
Less or equal |
|
|
|
Greater than |
|
|
|
Greater or equal |
|
Numeric Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Addition |
|
|
|
Subtraction |
|
|
|
Multiplication |
|
|
|
Division |
|
|
|
Modulo |
|
|
|
Absolute value |
|
|
|
Floor |
|
|
|
Round |
|
Type Operations
|
Operation |
Description |
Example |
|---|---|---|
|
|
Instance of type or subtype |
|
|
|
Exact type match |
|
|
|
Cast to type |
|
|
|
Get the type |
|
|
|
Is null/undefined |
|
Conditional Expressions
If-Then-Else
if condition then
trueValue
else
falseValue
endif
Example:
if self.isAbstract then 'abstract ' else '' endif
Nested Conditionals
if self.visibility = 'public' then 'public'
else if self.visibility = 'protected' then 'protected'
else 'private'
endif endif
Let Expressions
Define local variables:
let name = self.name.toUpper() in
name.concat('_CONSTANT')
Multiple bindings:
let upper = self.name.toUpper() in
let prefix = 'PREFIX_' in
prefix.concat(upper)
Lambda Expressions
Used in collection operations:
-- Simple lambda
self.attributes->select(a | a.isRequired)
-- Lambda with type annotation
self.attributes->select(a : Attribute | a.isRequired)
-- Multiple conditions in lambda
self.attributes->select(a | a.isRequired and a.visibility = 'public')
Null Safety
AQL handles null values gracefully:
-- Check for null
self.package.oclIsUndefined()
-- Safe navigation (returns null if package is null)
self.package.name
-- Default value pattern
if self.package.oclIsUndefined() then 'default' else self.package.name endif
Evaluation Order
-
Literals and variables are evaluated first
-
Navigation proceeds left to right
-
Operations are called on their receivers
-
Lambdas create closures evaluated per element
-
Conditionals evaluate branches lazily
Best Practices
-
Use meaningful lambda parameters:
select(attr | ...)notselect(x | ...) -
Chain operations:
select(...)->collect(...)->first()for efficiency -
Check for null: Use
oclIsUndefined()before nullable navigation -
Prefer
selectover iteration: More declarative and efficient -
Extract complex queries: Define as separate named queries
OCL Compatibility
AQL is based on OCL but differs in:
-
Arrow syntax: AQL uses
->for all collection operations -
Simplified syntax: Less verbose than full OCL
-
Lambda syntax: Uses
|instead of more complex OCL syntax
Next Steps
-
Getting Started with AQL - Practical examples
-
AQLExpression - Expression API
-
AQLCollectionOperations- Collection operations reference -
AQLExecutionContext - Execution configuration
See Also
Related Documentation
Essentials
Learn how to add AQL to your project and write your first model queries.