Перейти к основному содержимому
Версия: 7.0

Hierarchy

Модуль Hierarchy даёт классу иерархию по родителю: объект ссылается свойством parent[class] на объект того же класса, а модуль достраивает по этой ссылке признак предка, уровень, число потомков, признак листа и полное имя от корня. Свойство level[class, class] вычисляется рекурсией; остальные свойства выводятся из него или прямо из parent[class], где нужно — группировкой или разбиением; материализованные свойства отмечены в таблице ниже. Подключается через REQUIRE Hierarchy.

Подключение к классу

Иерархию добавляет один из трёх метакодов; различаются они тем, откуда берётся свойство parent[class]. У класса должно быть свойство name[class]: из него вычисляются nameParent[class] и canonicalName[class].

МетакодСвойство parent[class]
@defineHierarchy(object), @defineHierarchy(object, class)Объявляется первичным свойством класса; при создании объекта с включённой автоматической установкой оно получает текущий объект того же класса, если такой есть
@defineHierarchyAbstract(object), @defineHierarchyAbstract(object, class)Объявляется абстрактным материализованным свойством класса; реализацию добавляет прикладной модуль
@defineHierarchyCustom(object, class)Не объявляется: используется уже имеющееся в классе parent[class]

В форме с одним аргументом класс получается из object заменой первой буквы на прописную: @defineHierarchy(itemGroup) — то же, что @defineHierarchy(itemGroup, ItemGroup). Аргумент object становится также именем свойства «предок по уровню» и основой производных от него имён (см. таблицу ниже).

Свойства иерархии

Все три метакода добавляют классу один и тот же набор свойств (class — класс объектов, object — первый аргумент метакода; у свойств с двумя параметрами первый — потомок, второй — предполагаемый предок).

СвойствоЗначение
nameParent[class]name[class] родителя; помещается в группу base
level[class, class]Не NULL, если второй объект — предок первого или он сам; значение (класса LONG) — 2 в степени расстояния между ними: 1 для самого объекта, 2 для родителя, 4 для родителя родителя и так далее. При политике CYCLES NO, действующей по умолчанию, расстояние не может превышать 30: более длинная цепочка предков нарушает ограничение рекурсии, и сохранение отменяется. Материализовано
isParent[class, class]TRUE там, где level[class, class] не NULL: признак «предок или сам объект»
object[class, LONG]Предок первого аргумента, для которого level[class, class] равно второму аргументу (1 — сам объект, 2 — родитель, 4 — родитель родителя); имя свойства — аргумент object, например itemGroup[ItemGroup, LONG]
level[class]Уровень объекта — количество его предков вместе с ним самим (1 для корня). Материализовано
levelRoot[class, class]Номер предка в цепочке от корня к объекту: 1 для корня, level[class] объекта для него самого. Материализовано
objectRoot[class, INTEGER]Предок первого аргумента, стоящий на позиции второго аргумента от корня (1 — корень); имя — аргумент object с суффиксом Root, например itemGroupRoot[ItemGroup, INTEGER]
childNumber[class]Количество непосредственных потомков; NULL, если их нет. Материализовано
descendantNumber[class]Количество объектов, для которых данный — предок, включая его самого. Материализовано
isLeaf[class]TRUE, если непосредственных потомков нет. Материализовано
isParentLeaf[class, class]isParent[class, class] при условии, что первый объект — лист
canonicalName[class]Полное имя: name[class] предков от корня до самого объекта через / (ISTRING[255]). Материализовано

Дополнительные метакоды

Дополнительные метакоды рассчитывают на уже добавленные свойства иерархии: @defineHierarchyPlain использует objectRoot[class, INTEGER], @defineHierarchyFilterisParent[class, class] и name[class]; их применяют после одного из трёх метакодов выше.

МетакодЧто добавляет
@defineHierarchyPlain(object)Материализованные свойства object1[class]object6[class] — предки объекта на позициях от 1 до 6 от корня, то есть objectRoot[class, INTEGER] с фиксированной позицией; удобны для плоских отчётов и колонок вида «категория / направление / группа». Класс берётся из object заменой первой буквы на прописную
@defineHierarchyFilter(object, class, property, caption)Локальное свойство filter###property###object[] класса STRING[255] с заголовком caption (например, filterNameItemGroup[] для @defineHierarchyFilter(ItemGroup, ItemGroup, name, ...); аргумент property влияет только на это имя) и два счётчика по поддереву объекта — inFilterName[class] и inIFilterName[class]: количество объектов поддерева, включая его самого, у которых name[class] содержит введённую строку, с учётом и без учёта регистра (NULL, если таких нет); ими фильтруют дерево по подстроке наименования

Язык

  • Инструкция META — объявление метакода и его применение инструкцией @, которой иерархия подключается к классу.
  • Заголовок модуляREQUIRE Hierarchy, подключающий модуль.

Примеры

CLASS Category 'Категория';
name 'Наименование' = DATA ISTRING[50] (Category);

@defineHierarchy(category); // parent, level, isParent, canonicalName, childNumber, isLeaf, ...

// книги категории и всех её подкатегорий
CLASS Book 'Книга';
category = DATA Category (Book);
inCategory (Book b, Category c) = isParent(category(b), c);

// корень ветки категории и её родитель
root (Category c) = categoryRoot(c, 1);
parentByLevel (Category c) = category(c, 2l);

FORM categories 'Категории'
OBJECTS c = Category
PROPERTIES(c) name, canonicalName, level, childNumber, isLeaf
;