AQL
Текст может содержать неточности, устаревшие данные или технические ошибки. Пожалуйста, проверяйте критически важную информацию перед использованием.
Acceleo Query Language — язык запросов к графу модели. Он только читает модель и никогда её не изменяет, статически типизирован и поддерживает автодополнение.

Как пишется выражение
Выражение на AQL всегда одиночное: здесь нет операторов и нет точек с запятой. Начинается оно с переменной, доступной в текущем контексте, и продолжается навигацией:
self.name
По характеристике переходят через точку, операции над коллекциями вызывают через стрелку:
self.outgoingRelationships->size()
. применяется к одиночному объекту, -> — к коллекции. Навигация по
многозначной характеристике через . даёт коллекцию, с которой дальше работают
через ->.
Оба оператора допускают и другой вид аргумента. -> считает одиночное значение
коллекцией из одного элемента, а null — пустой коллекцией, поэтому при
незаданном имени self.name->size() равно 0. . на коллекции переходит от
каждого элемента и объединяет результаты, поэтому
self.outgoingRelationships.target даёт коллекцию целевых объектов.
Видимые переменные
self — объект, на котором вычисляется выражение, типизированный своим
собственным метаклассом. Какой это объект, зависит от того, где выражение
выполняется, — см. Консоль выражений.
self типизирован, поэтому автодополнение знает его характеристики, а обращение
к характеристике, которой у типа нет, помечается ещё до запуска.
В документе self — это сам документ, а data — последовательность объектов,
из которых документ строится. Переменная, объявленная блоком, доступна
выражениям внутри этого блока и получает тип элемента той коллекции, которую
блок перебирает.
Типы и проверки типов
Типы записываются с префиксом метамодели и двойным двоеточием:
archimate::ApplicationComponent. Значения перечислений состоят из трёх
сегментов: archimate::FolderType::business.
oclIsKindOf(T) истинно для типа и его подтипов, oclIsTypeOf(T) — только для
точного типа, а oclAsType(T) приводит значение к T и открывает доступ к
характеристикам T. На коллекции ->filter(T) оставляет элементы заданного
типа и даёт результат с этим типом элемента.
Примеры
Для ArchiMate, где self — элемент:
У элемента есть имя:
self.name <> null and self.name.trim().size() > 0
Элемент с чем-то связан:
self.incomingRelationships->notEmpty() or self.outgoingRelationships->notEmpty()
Всё, что реализует этот элемент:
self.outgoingRelationships
->select(r | r.oclIsKindOf(archimate::RealizationRelationship))
->collect(r | r.target)
Компоненты приложений, обслуживаемые данным компонентом, отсортированные по имени:
self.outgoingRelationships
->select(r | r.oclIsKindOf(archimate::ServingRelationship))
->collect(r | r.target)
->filter(archimate::ApplicationComponent)
->sortedBy(e | e.name)
У каждого элемента ровно одно свойство owner:
self.properties->select(p | p.key = 'owner')->size() = 1
Имена соответствуют соглашению:
self.name.matches('[A-Z][A-Za-z ]*')
Для ArchiMate, где self — модель:
Все бизнес-процессы модели:
self.eAllContents(archimate::BusinessProcess)
Элементы, которых не касается ни одна связь:
self.eAllContents(archimate::ArchimateElement)
->select(e | e.incomingRelationships->isEmpty()
and e.outgoingRelationships->isEmpty())
Повторяющиеся имена внутри слоя приложений:
self.eAllContents(archimate::ApplicationElement)
->select(e | self.eAllContents(archimate::ApplicationElement)
->select(o | o.name = e.name)->size() > 1)
Элементы, лежащие в папке Business:
self.folders->select(f | f.type = archimate::FolderType::business)
->collect(f | f.elements)
Дополнительные материалы
Документация Acceleo Query Language
Справочник по языку
Форма выражения
Тело всегда состоит из одного выражения. Здесь нет операторов, нет присваивания
и нет синтаксиса комментариев. Дать значению имя можно только через let или
через переменную итератора.
| Синтаксис | Значение |
|---|---|
expr.feature | чтение структурной характеристики |
expr.operation(args) | вызов операции на одиночном значении |
expr->operation(args) | вызов операции на коллекции |
(expr) | группировка |
Операнды вычисляются до выполнения операции: у and и or считаются обе
стороны, какой бы ни оказалась левая. Исключение — if, где считается только
выбранная ветвь.
Там, где требуется определённый тип результата, выражение с другим выведенным типом помечается ещё до запуска.
Приоритет операторов
От высшего к низшему. Операторы одной строки связываются слева направо.
| Операторы | Категория |
|---|---|
. -> | навигация по характеристике, вызов операции |
not | логическое отрицание |
унарный - | арифметическое отрицание |
* / | умножение, деление |
+ - | сложение, вычитание |
< <= > >= = == <> != | сравнение |
and | конъюнкция |
or | дизъюнкция |
xor | исключающая дизъюнкция |
implies | импликация |
and связывает сильнее, чем or, а or — сильнее, чем xor, поэтому
true or true and false равно true. Конструкции if ... endif и let ... in
— самодостаточные операнды.
Литералы
| Синтаксис | Тип | Значение |
|---|---|---|
42 | Integer | целочисленный литерал; ведущий - — это оператор отрицания |
1.5 | Real | вещественный литерал; цифры обязательны по обе стороны точки |
'text' | String | строковый литерал; экранируются \' и \\ |
true, false | Boolean | логические литералы |
null | отсутствующее значение | |
Sequence{1, 2, 3} | Sequence(T) | упорядоченная, дубликаты сохраняются |
OrderedSet{1, 2} | OrderedSet(T) | упорядоченная, дубликаты отбрасываются |
Sequence{}, OrderedSet{} | пустые коллекции | |
archimate::FolderType::business | перечисление | литерал перечисления: пакет, перечисление, значение |
Синтаксис типов
Тип — это тоже выражение, поэтому его можно передать как аргумент.
| Синтаксис | Значение |
|---|---|
String, Integer, Real, Boolean | примитивные типы |
archimate::BusinessActor | метакласс, уточнённый пакетом своей метамодели |
ecore::EObject, ecore::EClass | Ecore зарегистрирована всегда, поэтому её типы доступны в любом выражении |
Sequence(T) | тип последовательности |
OrderedSet(T) | тип упорядоченного множества |
{archimate::Node | archimate::Device} | набор типов — там, где операция принимает несколько |
Операции, принимающие несколько типов, понимают эту форму:
self.eAllContents({archimate::BusinessActor \| archimate::BusinessRole}).
Операции над любым значением
| Синтаксис | Возвращает | Значение |
|---|---|---|
a = b, a == b | Boolean | равенство |
a <> b, a != b | Boolean | неравенство |
v.oclIsKindOf(T) | Boolean | v — это T или подтип T |
v.oclIsTypeOf(T) | Boolean | v — в точности T |
v.oclAsType(T) | T | v как T, с доступом к характеристикам T |
v.toString() | String | строковое представление v |
v + s | String | v, приведённое к строке и соединённое с s — 42 + ' times' даёт '42 times' |
v.lineSeparator() | String | разделитель строк текущей платформы |
v.trace() | String | описание метамоделей и сервисов, в контексте которых выполняется выражение |
Операции сравнения
Применимы к числам и строкам — значениям с естественным порядком.
| Синтаксис | Возвращает | Значение |
|---|---|---|
a < b, a.lessThan(b) | Boolean | a меньше b |
a <= b, a.lessThanEqual(b) | Boolean | a меньше b или равно ему |
a > b, a.greaterThan(b) | Boolean | a больше b |
a >= b, a.greaterThanEqual(b) | Boolean | a больше b или равно ему |
Логические операции
Каждый оператор можно вызвать и по имени.
| Синтаксис | Возвращает | Значение |
|---|---|---|
a and b, a.and(b) | Boolean | конъюнкция |
a or b, a.or(b) | Boolean | дизъюнкция |
a xor b, a.xor(b) | Boolean | исключающая дизъюнкция |
a implies b, a.implies(b) | Boolean | истина всегда, когда a ложно |
not a, a.not() | Boolean | отрицание |
Операции над строками
Позиции нумеруются с единицы; границы substring входят в результат.
| Синтаксис | Возвращает | Значение |
|---|---|---|
s + t, s.concat(t) | String | конкатенация |
s.size() | Integer | число символов |
s.at(i) | String | символ на позиции i — 'cat'.at(2) даёт 'a' |
s.characters() | Sequence(String) | по одной записи на символ |
s.substring(lower) | String | от lower до конца — 'HelloWorld'.substring(6) даёт 'World' |
s.substring(lower, upper) | String | 'HelloWorld'.substring(1, 5) даёт 'Hello' |
s.first(n) | String | первые n символов или все, если s короче |
s.last(n) | String | последние n символов или все, если s короче |
s.prefix(p) | String | s с p впереди — 'World'.prefix('Hello') даёт 'HelloWorld' |
s.contains(t), s.strstr(t) | Boolean | t встречается в s |
s.startsWith(t) | Boolean | s начинается с t |
s.endsWith(t) | Boolean | s заканчивается на t |
s.equalsIgnoreCase(t) | Boolean | равенство без учёта регистра |
s.matches(regex) | Boolean | вся строка s соответствует регулярному выражению |
s.index(t) | Integer | позиция первого t, -1 при отсутствии |
s.index(t, from) | Integer | позиция первого t начиная с from |
s.lastIndex(t) | Integer | позиция последнего t, -1 при отсутствии |
s.lastIndex(t, from) | Integer | позиция последнего t при поиске назад от from |
s.strcmp(t) | Integer | отрицательное, ноль или положительное — t идёт до s, совпадает с ним или идёт после; верхний регистр сортируется раньше нижнего |
s.replace(regex, r) | String | заменить первое совпадение с регулярным выражением |
s.replaceFirst(regex, r) | String | заменить первое совпадение с регулярным выражением |
s.replaceAll(regex, r) | String | заменить все совпадения с регулярным выражением |
s.substitute(t, r) | String | заменить первое буквальное вхождение t |
s.substituteFirst(t, r) | String | заменить первое буквальное вхождение t |
s.substituteAll(t, r) | String | заменить все буквальные вхождения t |
s.toUpper() | String | все символы в верхнем регистре |
s.toLower() | String | все символы в нижнем регистре |
s.toUpperFirst() | String | первый символ в верхнем регистре |
s.toLowerFirst() | String | первый символ в нижнем регистре |
s.trim() | String | убрать пробельные символы в начале и в конце |
s.removeLineSeparators() | String | убрать все разделители строк |
s.removeEmptyLines() | String | убрать все пустые строки |
s.tokenize() | Sequence(String) | разбить по пробельным символам |
s.tokenize(delimiter) | Sequence(String) | разбить по заданному разделителю |
s.isAlpha() | Boolean | все символы — буквы |
s.isAlphaNum() | Boolean | все символы — буквы или цифры |
s.toInteger() | Integer | разобрать как целое число |
s.toReal() | Real | разобрать как вещественное число |
s.toBoolean() | Boolean | разобрать как логическое значение |
Операции над числами
Каждая из них применима и к Integer, и к Real.
| Синтаксис | Возвращает | Значение |
|---|---|---|
a + b | Integer, Real | сложение |
a - b | Integer, Real | вычитание |
a * b | Integer, Real | умножение |
a / b | Integer, Real | деление |
-a, a.unaryMin() | Integer, Real | отрицание |
a.abs() | Integer, Real | модуль |
a.floor() | Integer | целая часть — 3.14.floor() даёт 3 |
a.round() | Integer | ближайшее целое — 3.14.round() даёт 3 |
a.min(b) | Integer, Real | меньшее из двух |
a.max(b) | Integer, Real | большее из двух |
a.div(b) | Integer | целочисленное частное — 7.div(3) даёт 2 |
a.mod(b) | Integer | целочисленный остаток — 7.mod(3) даёт 1 |
a.toInteger() | Integer | как целое число |
a.toDouble() | Real | как вещественное число |
a.toLong() | длинное целое | как более широкое целое |
a.toFloat() | вещественное одинарной точности | как более узкое вещественное |
Синтаксис типов знает только Integer и Real. toLong и toFloat дают более
широкое целое и более узкое вещественное — их исполняющая среда различает внутри
себя.
Виды коллекций и преобразования
Видов коллекций два. Sequence упорядочена и сохраняет дубликаты, OrderedSet
упорядочена и отбрасывает их.
| Синтаксис | Возвращает | Значение |
|---|---|---|
c->asSequence() | Sequence(T) | как последовательность, дубликаты сохраняются |
c->asSet() | OrderedSet(T) | как упорядоченное множество, дубликаты отбрасываются |
c->asOrderedSet() | OrderedSet(T) | как упорядоченное множество, дубликаты отбрасываются |
Операция над коллекцией сохраняет её вид: ->select на последовательности даёт
последовательность, а на упорядоченном множестве — упорядоченное множество.
Операции над коллекциями
Индексы нумеруются с единицы.
| Синтаксис | Возвращает | Значение |
|---|---|---|
c->size() | Integer | число элементов |
c->isEmpty() | Boolean | нет ни одного элемента |
c->notEmpty() | Boolean | есть хотя бы один элемент |
c->first() | T | первый элемент |
c->last() | T | последний элемент |
c->at(i) | T | элемент на позиции i |
c->reverse() | тот же вид | элементы в обратном порядке |
c->includes(v) | Boolean | v входит в c |
c->excludes(v) | Boolean | v не входит в c |
c->includesAll(other) | Boolean | все элементы other входят в c |
c->excludesAll(other) | Boolean | ни один элемент other не входит в c |
c->count(v) | Integer | число вхождений v; в упорядоченном множестве 0 или 1 |
c->indexOf(v) | Integer | позиция первого v |
c->lastIndexOf(v) | Integer | позиция последнего v |
c->indexOfSlice(other) | Integer | позиция первого вхождения other подряд идущим отрезком |
c->lastIndexOfSlice(other) | Integer | позиция последнего вхождения other подряд идущим отрезком |
c->startsWith(other) | Boolean | c начинается с элементов other |
c->endsWith(other) | Boolean | c заканчивается элементами other |
c->sum() | Integer, Real | сумма элементов |
c->min() | Integer, Real | наименьший элемент |
c->max() | Integer, Real | наибольший элемент |
c->including(v) | тот же вид | c с добавленным в конец v |
c->excluding(v) | тот же вид | c без v |
c->append(v) | тот же вид | c с добавленным в конец v |
c->prepend(v) | тот же вид | c с добавленным в начало v |
c->insertAt(i, v) | тот же вид | c с v, вставленным на позицию i |
c + other, c->add(other) | тот же вид | элементы обеих коллекций |
c->concat(other) | тот же вид | элементы обеих коллекций |
c - other, c->sub(other) | тот же вид | элементы c, которых нет в other |
c->union(other) | тот же вид | элементы обеих коллекций, дубликаты отбрасываются |
c->intersection(other) | тот же вид | элементы, входящие в обе коллекции |
c->drop(i) | тот же вид | элементы после позиции i |
c->dropRight(i) | тот же вид | элементы до позиции i |
c->subSequence(from, to) | Sequence(T) | элементы с from по to включительно |
c->subOrderedSet(from, to) | OrderedSet(T) | элементы с from по to включительно |
c->filter(T) | коллекция T | элементы заданного типа или набора типов |
c->sep(s) | Sequence | s, вставленное между элементами |
c->sep(prefix, s, suffix) | Sequence | то же самое, обёрнутое в prefix и suffix |
c->sep(prefix, s, suffix, ifEmpty) | Sequence | то же самое; ifEmpty, равное false, даёт пустой результат для пустой c |
filter принимает метакласс, примитивный тип или набор типов:
c->filter(archimate::Node), c->filter(String),
c->filter({archimate::Node \| archimate::Device}).
Итераторы
Итератор принимает лямбду, которая записывается как имя переменной, | и
выражение. Переменной можно указать тип:
self.eContents()->select(e : archimate::Node | e.name <> null)
| Синтаксис | Возвращает | Значение |
|---|---|---|
c->select(e | cond) | тот же вид | элементы, для которых cond истинно |
c->reject(e | cond) | тот же вид | элементы, для которых cond ложно |
c->collect(e | expr) | тот же вид | результат expr для каждого элемента, объединённый в одну коллекцию |
c->any(e | cond) | T | первый элемент, для которого cond истинно |
c->exists(e | cond) | Boolean | cond истинно хотя бы для одного элемента |
c->forAll(e | cond) | Boolean | cond истинно для каждого элемента |
c->one(e | cond) | Boolean | cond истинно ровно для одного элемента |
c->isUnique(e | expr) | Boolean | expr даёт разное значение для каждого элемента |
c->sortedBy(e | key) | тот же вид | элементы, упорядоченные по key |
c->closure(e | expr) | OrderedSet | expr применяется повторно, пока не перестанет давать новые элементы |
closure проходит по цепочке: self->closure(e | e.eContainer()) — это список
контейнеров вплоть до корня.
Навигация по модели
| Синтаксис | Возвращает | Значение |
|---|---|---|
o.eContents() | Sequence(EObject) | объекты, непосредственно содержащиеся в o |
o.eContents(T) | Sequence(T) | то же самое, одного типа или набора типов |
o.eAllContents() | Sequence(EObject) | всё содержимое на любой глубине |
o.eAllContents(T) | Sequence(T) | то же самое, одного типа или набора типов |
o.eContainer() | EObject | содержащий объект |
o.eContainer(T) | T | ближайший контейнер заданного типа |
o.eContainerOrSelf(T) | T | сам o, если он T, иначе его ближайший контейнер этого типа |
o.eClass() | EClass | метакласс o |
o.eContainingFeature() | EStructuralFeature | характеристика контейнера, в которой лежит o |
o.eContainmentFeature() | EReference | ссылка-композиция, в которой лежит o |
o.eGet(name) | Object | значение характеристики, названной строкой |
o.eGet(feature) | Object | значение характеристики, заданной объектом |
o.eGet(feature, resolve) | Object | то же самое; resolve, равное false, оставляет прокси неразрешёнными |
o.eCrossReferences() | Sequence(EObject) | объекты, на которые o ссылается, но не содержит |
o.eInverse() | OrderedSet(EObject) | объекты, ссылающиеся на o |
o.eInverse(T) | OrderedSet(T) | то же самое, одного типа |
o.eInverse('feature') | OrderedSet(EObject) | объекты, ссылающиеся на o через названную характеристику |
o.ancestors() | Sequence(EObject) | все контейнеры o, начиная с ближайшего |
o.ancestors(T) | Sequence(T) | то же самое, одного типа или набора типов |
o.siblings() | Sequence(EObject) | остальные объекты в том же контейнере |
o.siblings(T) | Sequence(T) | то же самое, одного типа или набора типов |
o.precedingSiblings() | Sequence(EObject) | соседи, идущие до o |
o.precedingSiblings(T) | Sequence(T) | то же самое, одного типа или набора типов |
o.followingSiblings() | Sequence(EObject) | соседи, идущие после o |
o.followingSiblings(T) | Sequence(T) | то же самое, одного типа или набора типов |
eInverse читает обратные ссылки, которые отслеживаются по всему проекту, и
потому находит ссылающиеся объекты и в других моделях. В консоли и в документе
он работает, в правиле проверки и в быстром исправлении — возвращает пустое
множество. Поэтому проверка, которой нужно узнать, что ссылается на объект, идёт
по характеристике — как self.incomingRelationships.
Операции над ресурсами
| Синтаксис | Возвращает | Значение |
|---|---|---|
o.eResource() | Resource | ресурс, содержащий o |
o.getURIFragment() | String | фрагмент, идентифицирующий o внутри его ресурса |
r.getURI() | URI | URI ресурса |
r.getContents() | Sequence(EObject) | корни ресурса |
r.getContents(T) | Sequence(T) | корни заданного типа |
r.getEObject(fragment) | EObject | объект, который идентифицирует фрагмент |
u.lastSegment() | String | последний сегмент URI |
u.fileExtension() | String | расширение файла в URI |
u.isPlatformResource() | Boolean | это platform resource URI |
u.isPlatformPlugin() | Boolean | это platform plugin URI |
Условия и связывание имён
| Синтаксис | Возвращает | Значение |
|---|---|---|
if cond then a else b endif | тип ветвей | условное выражение; else и endif обязательны |
let n = expr in body | тип body | связать имя на остаток выражения |
let n : T = expr in body | тип body | то же самое, с явно указанным типом |
let n = e1, m = e2 in body | тип body | связать несколько имён сразу |
e | expr | лямбда, которую принимают итераторы | |
e : T | expr | то же самое, с явно указанным типом переменной |
let named = self.eAllContents(archimate::ArchimateElement)
->select(e | e.name <> null)
in named->size()
Операции, объявленные метамоделью
Операции, объявленные метамоделью на её метаклассах, вызываются как любые другие. В ArchiMate есть, среди прочих:
| Синтаксис | Возвращает | Значение |
|---|---|---|
o.getArchimateModel() | ArchimateModel | модель, которой принадлежит объект |
o.getArchimateConcept() | ArchimateConcept | концепт, который представляет объект диаграммы |
o.getDiagramModel() | DiagramModel | диаграмма, которой принадлежит объект диаграммы |
Автодополнение предлагает их наравне со встроенными.
Операции, ничего не возвращающие здесь
Они входят в язык и разбираются без ошибок, но в этом продукте им нечего читать.
| Синтаксис | Поведение |
|---|---|
T.allInstances() | сообщает, что провайдер корней не зарегистрирован, и даёт пустую коллекцию; чтобы добраться до всех экземпляров, используйте eAllContents от корня модели |
s.promptString(), s.promptInteger(), s.promptLong(), s.promptFloat(), s.promptDouble() | читают из терминала, которого у серверного выражения нет |
key.getProperty(), key.getProperty(args) | читают набор свойств, который пуст |