Частные случаи реализации скриптовых сценариев

Использование аннотации @DependsOn

Аннотация @DependsOn позволяет обозначить зависимость скрипта от одного или нескольких атрибутов контекстной переменной subject. Информация о зависимостях сохраняется в метаинформации вместе со скриптом. Этой аннотацией может быть помечен любой элемент скрипта (класс, переменная, метод).

Аннотация не влияет на поведение помеченных ей элементов, поэтому применять еe можно различными способами:

  1. Создать специальную служебную переменную с произвольным именем и пометить ее аннотацией, таким образом можно все зависимости наглядно описать в начале скрипта:

    @DependsOn('someAttr')
    def dependencies;
    // ...
  2. Применить аннотацию к переменной для хранения результата выполнения скрипта:

    @DependsOn('someAttr')
    def result = subject.someAttr.status.code == 'e'
    return result
  3. Пометить аннотацией функцию, которая использует внутри значение указанного атрибута subject, и таким образом наглядно локализовать место использования атрибута:

    @DependsOn('someAttr')
    def compute() {
    subject.someAttr.status.code == 'e'
    }
    return compute()

Можно комбинировать указанные варианты любым способом для достижения максимальной читаемости скрипта:

  • указывать несколько зависимостей сразу, передавая массив:

    @DependsOn(['someAttr', 'someOtherAttr'])

  • указывать несколько аннотаций подряд:

    @DependsOn('someAttr')
    @DependsOn('someOtherAttr')

Зависимости можно указывать только в виде константных значений:

// ...
def attrs = someFunction()
@DependsOn(attrs) // ошибка компиляции скрипта
def dependencies
// ...

Аннотация @DependsOn используется в скриптах:

Использование аннотации позволяет принимать решения о том, значения каких атрибутов subject уже должны иметь актуальное значение перед выполнением скрипта. В соответствии с этим корректируется порядок выполнения бизнес-процесса, в котором участвует скрипт. Циклические зависимости атрибутов друг от друга обнаруживаются стандартным образом, при попытке построения конкретного бизнес-процесса с участием взаимно зависимых атрибутов (например, добавление запроса). Аннотация носит информационный характер, ее использование в других скриптах не приведет к появлению ошибок.

Скрипт фильтрации значений и ограничения по типам

Известная проблема: в ссылочных атрибутах при настройке ограничения связи по типам в поле "Типы объектов" при установке флажка у класса или типа, автоматически проставляются флажки у вложенных типов, см. Ограничение связи по типам объектов.

Обходное решение: настроить ограничение по типам и добавить скрипт фильтрации значений при редактировании, см. Скрипт фильтрации значений атрибута при редактировании.

В скрипте фильтрации значений при редактировании используется:

  • метод utils.find, который возвращает также объекты типов и подтипов, см. Методы API;
  • переменная permittedFqns.

Пример:

  • В системе создана следующая иерархия классов и типов:

    class 1:
       type1
           type3
               type6
       type2
  • В class 2 создаем атрибут типа "Набор ссылок на БО" на class. В поле "Типы объектов" устанавливает флажки к типов type2, type3. При сохранении автоматически добавится type6, который необходимо исключить.
  • Для атрибута добавляем следующий скрипт фильтрации значений при редактировании:

    if(null == subject) {return []}
    def obj = []
    logger.info('==1==' + permittedFqns.toString())
    // перезаписываем переменную, исключив лишний тип6
    permittedFqns=['class$type2', 'class$type3'] 
    logger.info('==2==' + permittedFqns.toString())
    
    permittedFqns.each{
    logger.info('==!==' + it.toString())
    // tokenize - аналог split
    obj+=utils.find('сlass',['metaClass':it.tokenize('$')[1]]) 
    }
    logger.info('==3==' + obj.title.toString())
    return obj

Если задать permittedFqns и поиск в цикле сделать obj+=utils.find(it,[:]), то объект type6 будет найден, потому что является вложенным в type3.