===========================
Customizing a Rule Set
===========================
An installation often needs more than the shipped rules offer: its own
identifier types, a few institution-specific item types, a recommendation
that applies only to its agendas. Such changes are made in an **addon
package**: a separate package that depends on the package it customizes and
contributes to that package's rule set. The customized package itself is
never modified, so it can be upgraded independently and the addon keeps
working.
An addon package can:
- add specifications to item types of another package and place them among
the existing ones;
- define its own item types and make them part of another package's rule
set;
- add rules to another package's rule set: availability of items,
validation, scenarios of new units of description;
- restrict its rules to selected parts of a fund through an arrangement
extension.
The examples below follow the test package
:file:`elza-core/src/test/resources/rules-addon-test` of the ELZA sources,
which customizes ZP2015.
Structure of an addon package
=============================
.. code-block:: text
package.xml
rul_item_type.xml own item types (optional)
rul_item_spec.xml own specifications (optional)
rul_rule_set/ZP2015/ contributions to the ZP2015 rule set
rul_arrangement_rule.xml
rul_arrangement_extension.xml (optional, for scoped rules)
rul_extension_rule.xml (optional, for scoped rules)
rules/*.drl
The addon declares a dependency on the customized package:
.. code-block:: xml
ADDON_TEST
Addon test package
2
...
The addon does not list the ZP2015 rule set in a :file:`rul_rule_set.xml`
of its own; a directory :file:`rul_rule_set/ZP2015/` is enough. Its rules are
stored as part of the addon: deleting the addon removes them and restores
the rule set as the customized package defines it.
Conventions:
- **Code prefix.** All codes of the addon (item types, specifications, rule
files, extensions) start with the addon's own prefix, never with the prefix
of the customized package. A specification named ``ZP2015_...`` in an addon
would collide with a future version of ZP2015.
- **Priority 200 or more.** The ZP2015 and CZ_BASE rules have priority 100.
Rules of an addon must have a higher priority so they run after them and
can rely on, and override, their decisions.
- **Dependency version.** ``min-version`` is the version of the customized
package the addon was tested with.
Specifications for an item type of another package
==================================================
A specification is attached to an item type by ````. The
item type may belong to another package:
.. code-block:: xml
Addon identifier
...
addon id
.. _customization-spec-order:
Position of the specification
-----------------------------
Without ``view-after`` the specifications of an addon come after all
specifications of the packages it depends on. ``view-after`` names a
specification of the same item type after which the new one is placed, so
archivists find it next to related specifications:
- several specifications placed after the same specification keep the order
in which the addon lists them;
- a specification may be placed after another specification of the addon,
which forms a chain;
- the position is kept when the customized package is upgraded, because the
order is recomputed after every import;
- when the named specification does not exist (or the placements form a
cycle), the specification is placed last and the import logs a warning.
Offering the specification
--------------------------
Attaching a specification does not yet offer it to archivists: during the
evaluation of a unit of description every specification starts as
impossible, and only a rule allows it. Some ZP2015 item types allow all
their specifications generically (``ZP2015_OTHER_ID``,
``ZP2015_UNIT_DAMAGE_TYPE`` and the languages); a specification added to
them is offered wherever the item type is. For other item types the addon
adds a rule:
.. code-block:: text
rule "ADT_002 Addon identifier specification is possible on folders"
no-loop
when
$activeLevel : ActiveLevel( )
DescItem(type=="ZP2015_LEVEL_TYPE" && specCode=="ZP2015_LEVEL_FOLDER") from $activeLevel.descItems
$itemType : RulItemTypeExt(code == "ZP2015_OTHER_ID")
$itemSpec : RulItemSpecExt(code == "ADT_OTHERID_TEST") from $itemType.rulItemSpecList
then
$itemSpec.setType(RulItemSpec.Type.POSSIBLE);
$itemSpec.setPolicyTypeCode("ZP2015_POL_BASIC");
end
Do not add specifications to item types whose rules and validations work
with individual specifications by code (for example
``ZP2015_LEVEL_TYPE``): the customized rules would not know the new
specification.
Rules
=====
Rule files are registered in :file:`rul_rule_set/ZP2015/rul_arrangement_rule.xml`
of the addon:
.. code-block:: xml
ATTRIBUTE_TYPES
200
CONFORMITY_INFO
200
ITEM_TYPE_FILTER
200
Availability (``ATTRIBUTE_TYPES``)
Facts: ``RulItemTypeExt`` for every item type with its
``RulItemSpecExt`` specifications, ``ActiveLevel`` (the evaluated unit of
description) and ``Level`` for it and its ancestors, with their
``DescItem`` items. A rule calls ``setType``, ``setMinType`` (raise only),
``setRepeatable`` or ``setPolicyTypeCode``. Because the addon runs after
the customized rules, it can also lower their decisions, for example
``setType(RulItemType.Type.IMPOSSIBLE)``.
Validation (``CONFORMITY_INFO``)
Uses the global ``DataValidationResults dvResults``; for example
``dvResults.createMissing("ADT_STAGE", "Addon stage is missing (rule ADT_001).", "ZP2015_POL_BASIC")``.
The message is shown to archivists as written, so write it in the
language of the installation.
New units of description (``NEW_LEVEL``)
Uses the global ``NewLevelApproaches results``; ``results.create(name)``
adds a scenario, ``addDescItem(typeCode, specCode)`` presets its items.
Validation results already stored for existing units of description are not
recalculated when an addon is imported; validate the affected funds again.
.. note::
Rule files are compiled when they are first used, not during the import.
A syntax error in an addon rule appears as an error on the first unit of
description evaluated after the import. Test an addon on a test
installation first.
.. _customization-item-types:
Own item types
==============
An addon defines its own item types in :file:`rul_item_type.xml`, with its
own code prefix. Two things make an item type usable in the customized rule
set:
1. an ``ATTRIBUTE_TYPES`` rule of the addon allows it on the units of
description where it belongs;
2. an ``ITEM_TYPE_FILTER`` rule adds it to the rule set's list of item types,
which the grid, the search filters, the add-item dialog and the AI
assistant use. The rule runs after the rule set's own filter, over the
same facts (``cz.tacr.elza.drools.model.ItemType``):
.. code-block:: text
package AddonTest;
import cz.tacr.elza.drools.model.ItemType;
rule "ADT filter"
when
$it: ItemType(code in ("ADT_STAGE"))
then
$it.setPossible();
end
.. todo::
Placing an own item type among the item types of the customized package
(form groups, tree title, grid columns) - requires composition of UI
settings from several packages, not available yet for these settings: a
rule-set :file:`ui_setting.xml` in an addon is refused when the
customized package already defines the same setting. Only
``output-defaults`` (:ref:`output-defaults`) and the global
``dao-import-level-settings`` are composed so far.
Rules for a part of a fund
==========================
A rule that should apply only to some funds, or to a part of a fund, is
attached to an **arrangement extension** of the addon. Archivists switch
the extension on for a unit of description in *Validation rules* on the
toolbar of the unit of description; it then applies to that unit and all
units below it.
:file:`rul_arrangement_extension.xml`:
.. code-block:: xml
Metro agenda
:file:`rul_extension_rule.xml`:
.. code-block:: xml
ATTRIBUTE_TYPES
200
Extension rules use the same facts as the rules of the rule set and run
after them. The supported rule types are ``ATTRIBUTE_TYPES``,
``CONFORMITY_INFO``, ``CONFORMITY_IMPACT`` and ``NEW_LEVEL``.
A specification that should be offered only where the extension is active
needs care when the customized package allows all specifications of its
item type (``ZP2015_OTHER_ID``): an ``ATTRIBUTE_TYPES`` rule of the addon
lowers the specification to impossible everywhere, and the extension rule
allows it again where the extension is active.
.. todo::
Not yet possible in an addon: placing own item types among the item types
of the customized package; contributing UI settings other than
``output-defaults`` for the customized rule set; extending a structured type of another package; removing a
scenario of a new unit of description; renaming codes. See the
development plan :file:`docs/rules-customization-layer-plan.md`.