Rt (jandcode.utils.rt.Rt) - это древовидная структура данных, где каждый
узел дерева имеет имя, атрибуты, дочерние элементы и предка.
Получить представление об Rt можно из этого примера (он будет использоваться в дальнейшем для объяснения некоторых понятий):
<root>
<field>
<sys attr1="1"/>
<number parent="field/sys" title="Int"/>
<long parent="field/number" title="Long"/>
<int parent="field/number" title="Int"/>
<string parent="field/sys" title="String" size="20"/>
</field>
<table>
<sys title="SysTable"/>
<id parent="table/sys">
<field>
<id parent="field/long" title="Id"/>
</field>
</id>
<tab1 parent="table/sys" title="Table1">
<field>
<name parent="field/string" title="Name" size="60"/>
</field>
</tab1>
<tab2 parent="table/tab1" title="Table2">
<field>
<name size="100"/>
<name2 parent="field/string" title="Name"/>
</field>
</tab2>
</table>
</root>
В этом примере описан объект с именем root, который имеет дочерние объекты
field, table. В свою очередь объект field имеет дочерние sys, string,
int и т.д.
Имена атрибутов и узлов - регистронезависимые.
Точка допустима в имени узла и имени атрибута.
Имена дочерних узлов (в пределах одного родителя) должны быть уникальны.
Каждый элемент характеризуется путем, в котором перечислены все его родительские элементы,
начиная (но не включая) корневой элемент. Элементы пути разделяются /.
В примере мы можем увидеть объекты с путями:
field/string
table/tab2/field/name2
Атрибут parent интерпретируется особым образом. В нем указывается путь объекта rt,
который является предком для этого. Если такой атрибут присутствует, то поиск
значения атрибута и дочерних элементов осуществляется вверх по иерерхии, начиная
с искомого. Первый найденный элемент будет возвращен.
Создание нового корневого объекта Rt:
Rt root = new RtRoot()
Для доступа к значениям атрибутов используются методы getValue/setValue.
В качестве параметра используется:
attribute_name- значение атрибутаattribute_nameобъектаpath:attribute_name- значение атрибутаattribute_nameу объекта по путиpath
Например:
root.getValue("field/string:title") // => String
Rt t1 = root.findChild("field/string")
t1.getValue("title") // => String
Для xml-файлов, которые написаны для хранения rt, используется расширение .rt.
При загрузке Rt из xml-файлов, каждый узел, имя которого не начинается с x-,
рассматривается как объект Rt. Его имя совпадает с именем узла.
Все атрибуты узла xml, имена которых не начинаются с x- рассматриваются как атрибуты
Rt-объекта. Все дочерние элементы xml рассматриваются как дочерние объекты Rt.
Если узел имеет атрибут name, то значение атрибута name интерпретируется
как имя дочернего узла, который описывается этим тегом. Например:
<root>
<table name="Tab1">
<field name="f1" title="F1"/>
<field name="f2" title="F1"/>
</table>
</root>
эквивалентно:
<root>
<table>
<Tab1>
<field>
<f1 title="F1"/>
<f2 title="F1"/>
</field>
</Tab1>
</table>
</root>
Если имя узла i, то оно заменяется на уникальное значение. Используется для
узлов, имя которых не важно:
<root>
<path>
<i value="c:/temp"/>
<i value="d:/temp"/>
</path>
</root>
Если узел имеет текст, то он сохраняется в атрибуте text:
<root>
<node>TEXT VALUE</node>
</root>
эквивалентно:
<root>
<node text="TEXT VALUE"></node>
</root>
Если коментарий начинается с символа @, то он сохраняется в атрибуте comment
того узла, внутри которого был встречен:
<root>
<node><!--@ COMMENT VALUE --></node>
</root>
эквивалентно:
<root>
<node comment="COMMENT VALUE"></node>
</root>
Атрибуты, имена которых начинается с x- обрабатываются специальным способом.
Устанавливает для узла флаг «виртуального корня». Для таких узлов все parent дочерних элементов обрабатываются относительно этого «виртуального корня». А если не найдено тут, то относительно реального корня. Используется для выделения частично независимых узлов в rt:
<root>
<node x-root="true"/>
</root>
Узлы, имена которых начинаются с x- обрабатываются особым способом.
Включение в узел, внутри которого встретился, файла (файлов) или другого узла. Файл грузится в один узел только один раз. При повторной загрузке - игнорируется. Этой особенностью можно воспользоваться для организации зависимостей.
Атрибуты:
path- путь до включаемого файла относительно текущего загружаемого. Может включать „*“ для загрузки группы файловrecursive- по умолчанию=false. При значении true - если в path есть „*“, то файлы рекурсивно ищутся в дочерних каталогах указанного пути.required- по умолчанию=true. При значении true - если файл не найден, генерируется ошибка. Иначе ошибка игнорируется.rtpath- если указан, рассматривается как путь уже загруженного объекта, содержимое которого накладывается на узел (и атрибуты и дети), внутри которого объявлена директива. Накладывается не только сам узел, указанный в атрибуте, но и все его предки. Раскрытие при наложении не производится.module- если указан, рассматривается как java-пакет, в котором должен лежать файлmodule.rt, который и загружается. Эквивалентно загрузке файлаres:MODULEPATH/module.rt.plugin- если указан, рассматривается как включение плагина загрузки в текущий узел. Т.е. выполняется метод плагинаjandcode.utils.rt.IRtPlugin#handleIncludeв контексте текущего узла.
Пример:
<root>
<x-include path="data/*.rt" recursive="true"/>
<table name="Abonent">
<x-include rtpath="includes/datatable"/>
</table>
</root>
Пример загрузки модулей:
<root>
<x-include module="myapp.module1"/>
<x-include module="myapp.module2"/>
</root>
Определение модуля.
Модулем является java-пакет, в котором есть файл module.rt и системный узел x-module
должен быть использован только в этом файле.
Атрибуты:
name- имя модуля. Должно совпадать с именем java-пакета, где расположенmodule.rt
Дочерние узлы:
depend- зависимость модуля. В атрибутеnameуказывается имя модуля, который должен быть включен до этого.
Пример:
<!-- file: d:/project/myproject/src/myproject/mymodule/module.rt -->
<root>
<x-module name="myproject.mymodule" any_attr="any_value">
<depend name="jandcode.app"/>
<depend name="jandcode.dbm"/>
<depend name="jandcode.web"/>
</x-module>
</root>
Узел отправляется на обработку всем плагинам загрузки (описанных в узлах x-plugin)
в метод handleSysChild. После обработки, узел модуля сохраняется как дочерний узла module:
<root>
<module>
<myproject.mymodule any_attr="any_value">
<depend>
<jandcode.app/>
<jandcode.dbm/>
<jandcode.web/>
</depend>
</myproject.mymodule>
</module>
</root>
Определение правила раскрытия сокращенных значений атрибута parent. Атрибуты:
pathregex для пути узлаparentvalueregex для значения атрибута parentreplaceна что заменять
Пример:
<root>
<x-parentexpander
path=".*domain/(.*?)/field/(.*?)"
parentvalue="^(\w*)$"
replace="field/$1"/>
</root>
Если для значения parent не определено правило и в нем нет /, то тогда используется
значение имя_владельца/значение_parent.
Если значение parent начинается с /, то раскрытие для него не производится.
Считается что указан явный абсолютный путь.
Определение атрибута с многострочным значением. В атрибуте name имя атрибута,
в тексте узла - значение атрибута. Пример:
<root>
<mynode attr1="a1">
<x-attr name="attr2">
a2-1
a2-2
</x-attr>
</mynode>
</root>
Определение плагина загрузки.
Плагином является класс, который участвует в процессе загрузки и может изменять
узел, внутри которого он был включен. Включение плагина в процесс загрузки
осуществляется через тег x-include, в атрибуте plugin которого
указывается имя включаемого плагина.
Атрибуты:
name- имя плагина. Должно быть уникальным среди всех плагинов. Можно не указывать, тогда имя генерируется. Плагины без имени нельзя будет использовать вx-includeclass- имя класса плагина загрузки. Должен реализовывать интерфейсjandcode.utils.rt.IRtPlugin. Если не указан, то должен быть указан атрибутpath.path- если указан и не указан атрибутclass, то подразумеватся специальный плагин, который будет включать в узел файл(ы), указанный в этом атрибутеостальные- атрибуты, которые передаются экземпляру плагина и используются им по своему усмотрению
Дочерние узлы:
depend- зависимость плагина. В атрибутеnameуказывается имя плагина, который должен быть использован до этого.
В значениях атрибутов и текста узлов раскрываются подстановки #{VAR}, где VAR:
path- абсолютный путь до текущего файлаpathup:FILENAME- абсолютный путь вверх до каталога, содержащего файлFILENAME, начиная с текущего каталогаpathprop:PROPNAME- значение изUtFile.getPathprop(String, String), начиная с текущего каталогаrt:RTPATH- значение по путиRTPATHиз загруженной к этому времени rtостальные- значение изSystem.getProperties()
В описаниях подстановок используются термины:
- текущий файл - файл, в котором встретилась подстановка
- текущий каталог - каталог, в котором лежит файл в котором встретилась подстановка
Пример:
<root>
<!-- attr1 равен пути, в котором лежит текущий файл -->
<n1 attr1="#{path}"/>
<!-- если текущий файл лежит в каталоге d:\projects\myproject\myconfig
и существут каталог d:\projects\myproject\dir\subdir
то значение attr1 равно d:\projects\myproject\dir\subdir\cfg1.rt
-->
<n2 attr1="#{pathup:dir/subdir}/cfg1.rt"/>
<!-- attr1 равен пути в временном каталоге d:\temp\myproject\myfile.txt -->
<n3 attr1="#{java.io.tmpdir}/myproject/myfile.txt"/>
<config>
<node1 value="123"/>
</config>
<!-- attr1 равен 123 -->
<n4 attr1="#{rt:config/node1:value}"/>
</root>