Формат файла cfx

Файл предназначен для загрузки объектов jandcode.commons.conf.Conf.

Расширение файла .cfx.

Содержимое файла в формате xml.

Корневой элемент xml описывает свойства загружаемого объекта.

Тег без атрибутов

Тег без атрибутов и без дочерних тегов, но с текстом - простое свойство объекта:

<root>
    <prop1>value1</prop1>
    <prop2>value2</prop2>
</root>

получаем:

{
    prop1: value1
    prop2: value2
}

Тег c атрибутами

Если тег с атрибутами, то имя тега рассматривается как имя свойства типа Conf, а все атрибуты - его свойства:

<root>
    <obj attr1="1" attr2="2"/>
</root>

получаем:

{
    obj: {
        attr1: 1
        attr2: 2
    }
}

Пустой тег

Если тег пустой (нет атрибутов, нет дочерних, нет текста), то имя тега рассматривается как имя свойства типа Conf без атрибутов:

<root>
    <obj1/>
    <obj2/>
</root>

получаем:

{
    obj1: {
    }
    obj2: {
    }
}

Дочерние теги

Дочерние теги рассматриваются как свойства объекта, чьими дочерними они являются:

<root>
    <obj1>
        <prop1>value1</prop1>
        <emptyobj/>
        <withattr attr1="1" attr2="2">
            <attr3>3</attr3>
            <emptyobj2/>
        </withattr>
    </obj1>
</root>

получаем:

{
    obj1: {
        prop1: value1
        emptyobj: {
        }
        withattr: {
            attr1: 1
            attr2: 2
            attr3: 3
            emptyobj2: {
            }
        }
    }
}

Атрибут name

Если у тега имеется атрибут name, то тег описывается свойство со значением атрибута name у объекта с именем тега, где атрибут встретился:

<root>
    <domain name="Domain1" domain-attr1="1">
        <field name="id" field-attr1="1"/>
        <field name="name1" field-attr1="2"/>
    </domain>
    <domain name="Domain2" domain-attr1="2">
        <field name="id" field-attr1="1"/>
        <field name="name2" field-attr1="2"/>
    </domain>
</root>

получаем:

{
    domain: {
        Domain1: {
            domain-attr1: 1
            field: {
                id: {
                    field-attr1: 1
                }
                name1: {
                    field-attr1: 2
                }
            }
        }
        Domain2: {
            domain-attr1: 2
            field: {
                id: {
                    field-attr1: 1
                }
                name2: {
                    field-attr1: 2
                }
            }
        }
    }
}

Безымянное свойство

Если свойство имеет имя i, то оно - безымянное и для него генерируется уникальное имя. Предназначено для описания списков:

<root>
    <list1>
        <i attr1="1"/>
        <i attr1="2"/>
        <i attr1="3"/>
    </list1>
    <list1 name="i" attr1="4"/>
</root>

получаем:

{
    list1: {
        #0: {
            attr1: 1
        }
        #1: {
            attr1: 2
        }
        #2: {
            attr1: 3
        }
        #3: {
            attr1: 4
        }
    }
}

Специальные символы в имени

В имени свойства комбинация символов '--' и символы '/', ':' заменяются на символ '!'. Используется для описания имен свойств с путями:

<root>
    <action name="my/action1" attr1="1"/>
    <action>
        <my--action2 attr1="1"/>
    </action>
</root>

получаем:

{
    action: {
        my!action1: {
            attr1: 1
        }
        my!action2: {
            attr1: 1
        }
    }
}

Специальный коментарий

Если коментарий начинается с символа '@', то его текст рассматривается как значение атрибута comment объекта, внутри которого встретился коментарий:

<root>
    <obj1>
        <!--@
            comment1
        -->
    </obj1>
    <field name="f1">
        <!--@
            comment2
        -->
    </field>
</root>

получаем:

{
    obj1: {
        comment: comment1
    }
    field: {
        f1: {
            comment: comment2
        }
    }
}

Функции

Если тег начинается с символов 'x-', то он описывает функцию с именем тега, без символов 'x-'. Такие функции обрабатываются особым способом с помощью плагинов загрузки jandcode.commons.conf.ConfLoaderPlugin.

Стандартные функции, доступные всегда, описаны ниже.

Функция: include

Загружает файлы в объект, внутри которого описана функция. Файл грузится в один объект только один раз. При повторной загрузке - игнорируется.

Параметры:

  • path - путь до включаемого файла относительно текущего загружаемого. Может включать маски, как в ant ('*', '**') для загрузки группы файлов
  • required - по умолчанию true. При значении true - если файл не найден, генерируется ошибка. Иначе ошибка игнорируется.

Пример:

<root>
     <x-include path="data/**/*.cfx"/>
     <model name="DefaultModel">
         <x-include path="default-model.cfx" required="false"/>
         <!-- игнорируется, повторная загрузка: -->
         <x-include path="default-model.cfx" required="false"/> 
     </model>
</root>

Функция: set

Установить произвольные переменные, которые в дальнейшем можно использовать в подстановках и условиях if/if-not

<root>

    <x-set var1="value1"/>
    <x-set var2="value2"/>

    <node1 attr1="#{var1} % #{var2}"/>

</root>

получаем:

{
    node1: {
        attr1: value1 % value2
    }
}

Функция: set-default

Функция аналогична set, за исключением того, что значение переменной устанавливается только если у нее еще нет значения.

<root>

    <x-set var1="value1"/>

    <x-set-default var1="default-value1"/>
    <x-set-default var2="default-value2"/>

    <node1 attr1="#{var1} % #{var2}"/>

</root>

получаем:

{
    node1: {
        attr1: value1 % default-value2
    }
}

Функция: if

Загружает тело тега в объект, если соблюдается условие. Условием является набор атрибутов. Каждый атрибут рассматривается как условие, где имя атрибута - имя переменной, значение атрибута - значение, которое должно быть у переменной.

<root>

    <x-set var1="value1"/>

    <node1>
        <x-if var1="value1">
            <node-for-value1/>
        </x-if>
    </node1>

</root>

получаем:

{
    node1: {
        node-for-value1: {
        }
    }
}

Функция: if-not

То же, что и if, только проверяется несоблюдение условия.

Подстановки

В значениях атрибутов раскрываются подстановки #{VAR}. Значения для переменных предоставляются плагинами загрузки jandcode.commons.conf.ConfLoaderPlugin.

Стандартные переменные, доступные всегда:

  • path - абсолютный путь до текущего файла. Если текущий путь в VFS (например внутри jar), то и результат будет в формате VFS. Соответственно для реальной файловой системы путь будет в формате реальной файловой системы
  • другое - значение соответствующей системной переменной из System.getProperties()

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

  • текущий файл - файл, в котором встретилась подстановка
  • текущий каталог - каталог, в котором лежит файл в котором встретилась подстановка

Пример:

<root>
    <!-- attr1 равен пути, в котором лежит текущий файл -->
    <n1 attr1="#{path}"/>

    <!-- attr1 равен пути в временном каталоге d:\temp\myproject\myfile.txt -->
    <n3 attr1="#{java.io.tmpdir}/myproject/myfile.txt"/>

</root>