Проектные расширения
Contents
Проектные расширения#
Точка расширения#
Аббревиатуры:
Ept
- Точка расширенияExt
- Расширения
Точка расширения (ExtensionPoint) – специфический пакет, методы которого объявлены таким образом, что к ним можно подключить дополнительный исполняемый код из других пакетов (расширений/Extension). Код расширений будет выполнен при вызове метода точки расширения.
class Btk_ExampleEpt extends ExtensionPoint {
val doSomeThing = declFunc("doSomeThing") {
(sf: SuperFunc[Int], a: Int, b: Int) =>
val superVal = sf().getOrElse(0)
a + b + superVal
}
}
object Btk_ExampleEpt extends PkgFactory[Btk_ExampleEpt]
Пример представляет объявление «Точки расширения» с методом
doSomeThing
Правила наименования для точек расширения, которые используются для
дополнения функционала сеттеров, вставки. удаления – Xxx_Ept
, где
Xxx
– имя модуля, для которого точка расширения создается (например
Bs_Ept
, Btk_Ept
).
Расширение (Extension) – специфический пакет, методы которого подключаются к методам точки расширения, и выполняются при вызове соответствующего метода точки расширения.
К методу точки расширения может быть подключено произвольное число методов расширений.
При первом обращении к классу точки расширения, производится поиск и
сканирование файлов META-INF/extensions.xml
. Расширения, у которых
свойство targetEpt
совпадает с именем точки расширения, подключаются к
точке расширения.
class Gs3_Btk_ExampleExt extends Extension {
subFunc("doSomeThing") {
(sf: SuperFunc[Int], a: Int, b: Int) =>
val superVal = sf(a - 2, b).getOrElse(0)
superVal + 2
}
}
Пример представляет объявление метода расширения. На вход метод получает ссылку на метод расширения, находящийся ниже в очереди вызовов.
Внимание
Если не вызвать sf()
, методы расширений, находящиеся ниже в очереди не будут вызваны.
Правила наименования для расширений, которые используются для дополнения
функционала других модулей для сеттеров, вставки. удаления –
Xxx_YyyExt
, где Xxx
– имя модуля расширения, Yyy
– имя модуля, в
котором находится точка расширения (например Mct_BsExt
).
Конфигурирование расширений#
Конфигурация расширений находится в файле META-INF/extensions.xml
.
Структура фала:
<?xml version="1.0" encoding="UTF-8"?>
<exts>
<ext class="ru.bitec.app.btk.ext.Btk_ExceptionHandlerExt"
targetEpt="ExceptionHandlerEpt"/>
</exts>
Порядок вызовов#
По умолчанию, метод точки расширения получает порядковый номер «0», а все методы расширений – номер «10». В результате, в первую очередь буду вызваны все методы расширений, в произвольном порядке, в конце будет вызван код точки расширения.
Для изменения порядка вызовов необходимо задать порядковые номера методам расширений.
subFunc("doSomeThing", 1) {
(sf: SuperFunc[Int], a: Int, b: Int) =>
}
Проектное перекрытие кода Api, Avi, Lib, Pkg#
Для перекрытия кода Api, Avi, Lib, Pkg необходимо:
Создать свой класс-наследник от перекрываемого класса.
Зарегистрировать перекрытие класса в файле
META-INF/overrides.xml
Пример перекрытия Avi-класса#
Код исходного Avi-класса Gs3_RootTestAvi.scala
#
object Gs3_RootTestAvi extends Gs3_RootTestAvi
@AvmFile(name = "Gs3_RootTest.avm.xml")
class Gs3_RootTestAvi extends Gs3_RootTestDvi {
override def list(): List = {
new List {
override def meta = this
}
}
}
Код перекрытия Avi-класса Gs3_RootTestOverrideAvi.scala
#
object Gs3_RootTestOverrideAvi extends Gs3_RootTestOverrideAvi
@AvmFile(name = "Gs3_RootTestOverride.avm.xml")
class Gs3_RootTestOverrideAvi extends Gs3_RootTestAvi {
override def list(): List = {
new List {
override def meta = this
}
}
trait List extends super.List {
}
}
Аннотация @AvmFile
может быть не указана, в этом случае будет
использоваться аннотация из класса-предка.
Текст META-INF/overrides.xml
#
<?xml version="1.0" encoding="UTF-8"?>
<overrides>
<replace-with
class="ru.bitec.app.gs3.test.Gs3_RootTestOverrideAvi">
<when-type-is class="ru.bitec.app.gs3.test.Gs3_RootTestAvi"/>
</replace-with>
</overrides>
Пример перекрытия Api#
Код перекрытия#
class Gs3_RootTestOverrideApi extends Gs3_RootTestApi {
}
object Gs3_RootTestOverrideApi extends ApiFactory[
java.lang.Long,
Gs3_RootTestAro,
Gs3_RootTestOverrideApi
]
Текст META-INF/overrides.xml
#
<replace-with
class="ru.bitec.app.gs3.test.collections.Gs3_RootTestOverrideApi">
<when-type-is
class="ru.bitec.app.gs3.test.collections.Gs3_RootTestApi"/>
</replace-with>
Пример перекрытия Pkg#
Код перекрытия#
class Btk_OverridePkg extends Btk_Pkg {
}
object Btk_OverridePkg extends PkgFactory[Btk_OverridePkg]
Текст META-INF/overrides.xml
#
<replace-with class="ru.bitec.app.gs3.Btk_OverridePkg">
<when-type-is class="ru.bitec.app.btk.Btk_Pkg"/>
</replace-with>
Пример перекрытия Lib#
Код перекрытия#
class Btk_OverrideLib extends Btk_Lib {
}
object Btk_OverrideLib extends AviLibFactory[Btk_Lib]
Текст META-INF/overrides.xml
#
<replace-with class="ru.bitec.app.gs3.Btk_OverrideLib">
<when-type-is class="ru.bitec.app.btk.Btk_Lib"/>
</replace-with>
Запрет перекрытия#
Для запрета проектного перекрытия кода Avi-класса, необходимо отметить класс аннотацией @Final.
@Final
class Gs3_RootTestAvi extends Gs3_RootTestDvi {}
Для запрета проектного перекрытия кода Api,Lib,Pkg классов, необходимо
отметить класс аннотацией @Final
или ключевым словом final
.
@Final
class Gs3_RootTestApi extends Gs3_RootTestDpi[
Gs3_RootTestAro,
Gs3_RootTestApi,
Gs3_RootTestAta
] {}
или
final class Gs3_RootTestApi extends
Gs3_RootTestDpi[
Gs3_RootTestAro,
Gs3_RootTestApi,
Gs3_RootTestAta
] {}
Jexl расширения методов#
С помощью расширений методов имеется возможность доработки и модификации стандартных серверных методов и операций пользовательских интерфейсов из приложения Настройки системы
.
Расширение представляет из себя jexl-скрипт, вызываемый перед или после выполнения стандартного метода/операции.
Расширения Api-методов#
Добавление точек расширения в Api
предусмотрено только в следующие методы:
Сеттеры атрибутов
–Dpi-
сеттеры всех атрибутов выбранного класса;AfterEdit
–Dpi-
метод, вызываемый на окончание редактирования объекта класса, например при редактировании строки и перемещении курсора на другую строку;BeforeEdit
–Dpi-
метод, вызываемый в начале редактирования объекта класса;FlushObject
– метод записи (сохранения) объекта в базу данных;Delete
–Dpi-
метод удаления объекта класса из базы данных;Insert
–Dpi-
метод создания нового объекта класса.
Примечание
Все расширения вызываются из „Dpi“. Т.е. срабатывание перед сеттером - это срабатывание перед вызовом Dpi-
сеттера.
Примечание
Для методов «FlushObject» и «BeforeEdit» можно добавлять только точки расширения «До».
Выполнение этих точек будет производиться в контексте сессии, без использования интерактивной бизнес логики (т.е. нельзя использовать методы открытия всплывающих окон и диалогов, открытия каких либо интерфейсов системы).
Для подключения точек расширения Api-методов перейдите: Настройки системы
- Обозреватель проекта
. Выбрав Api нужного класса, перейдите на закладку Точки расширения
.
На закладке Расширения до
или Расширения после
создайти запись нового расширения и пропишите ему исполняемый скрипт.
Пример скрипта с использованием вызова процедур из Bts:
Bts_ProcedureApi.execByMnemoCode("ProcedureCode", {"argName1": value1, "argName2": value2, ...})
Пример выброса ошибки, если у объекта не заполнен атрибут sDescription
:
var aro = rop.copyAro();
if (aro.sDescription() == null){
raise("Не заполнено описание!")
}
Расширения Avi-методов#
Добавление точек расширения в Avi
предусмотрено в сеттеры выборки, в ее операции или на события выборки, такие как beforeEdit, afterEdit и т.д.
Выполнение этих точек будет производиться в контексте выборки.
Для подключения точек расширения Avi-методов перейдите: Настройки системы
- Обозреватель проекта
. Выбрав нужную выборку, перейдите на закладку Редактор операций
.
На закладке Расширения до
или Расширения после
создайте запись нового расширения и пропишите ему исполняемый скрипт.
Пользовательские события#
Реализована возможность для Api
добавлять собственные события, а так же для существующих стандартных событий добавлять новые типы срабатывания.
Добавление нового события#
Новое событие будет отображено в списке событий Api
. Оно создается без типов срабатываний, типы срабатывание привязываются к событию отдельным методом.
Пример добавления нового события:
Btk_MethodExtensionApi().registerClassEvent(
idvClass,
"SomeUserEventName",
"Новое пользовательское событие"
)
Пример удаления пользовательского события:
Btk_MethodExtensionApi().unregisterClassEvent(
idvClass,
"SomeUserEventName"
)
Добавление типа срабатывания к событию#
Стандартные события (сеттеры, вставка и тд.) имеют по умолчанию 2 типа срабатывания: До
и После
, а пользовательские события создаются без типа срабатывания.
Реализована возможность добавления нового типа срабатывания к событию. Каждый тип срабатывания будет отображаться отдельной закладкой у события.
Создание нового типа срабатывания:
Btk_MethodExtensionTypeApi().register("SomeUserEventType", "На пересчет денормализации")
Создание связи между событием и типом срабатывания:
Btk_MethodExtensionApi().registerEventTypeToClassEvent(
idvClass,
"SomeUserEventName",
Btk_MethodExtensionTypeApi().findByMnemoCode("SomeUserEventType")
)
Удаление связи между событием и типом срабатывания:
Btk_MethodExtensionApi().unregisterEventTypeFromClassEvent(
idvClass,
"SomeUserEventName",
Btk_MethodExtensionTypeApi().findByMnemoCode("SomeUserEventType")
)
Вызов пользовательского события или пользовательского типа срабатывания из кода приложения#
Разработчик в коде сам размещает вызов срабатывания события в нужном месте.
Пример вызова:
Btk_MethodExtensionApi().runMethodExtensionByClass(idvClass, "SomeUserEventType", "SomeUserEventName", "valueStr" -> "abc", "valueNum" -> 1.nn)
Переданные в метод значения параметров будут доступны в Jexl-скриптах
этого события.
Пример обращения к переменной из Jexl-скрипта
:
println("Значение переменной valueStr: " + valueStr + " Значение переменной valueNum: " + valueNum.toString());