.. _mergeable-xml:
=============
Mergeable XML
=============
.. contents::
:local:
:depth: 3
Overview
========
Cloud Softphone and all apps based on Acrobits SDK allows various configurations to be provisioned from the server. At
the same time, the apps often contain "settings" or "preferences" GUI which lets the end user set various configuration
options.
In such a situation, collisions are possible. In case the values from settings GUI and from provisioing are simply
saved, values entered by end user will be overwritten by provisioning and vice versa, which leads to chaos and bad
user experience.
To overcome this, we created a simple system of merging the values based on priorities, which may be either set
explicitly, or be deduced automatically from where the values came from.
Data Model
==========
As the name suggests, Mergeable XML works with XML documents. These documents are treated as key-value stores, where
names of nodes which are children of the root nodes are the keys and content of these nodes are values. The node values
may be strings - text data inside the nodes, or xml sub-trees, in which case, the whole sub-tree is taken as a single
value.
.. important::
Mergeable XML document can be seen as a list of key-value pairs, where keys are strings and values may be either
strings, or XML sub-trees.
Example:
.. code-block:: xml
example.com
udp
This example defines a key-value store of three entries: host=>example.com, transport=>udp and rewriting=>(xml tree).
This is an actual example of :ref:`account-xml`, which uses Mergeable XML model.
The XML nodes which are immediate children of root node will be called ``key nodes`` and the content of these nodes
(either strings or XML sub-trees) will be called ``values``.
Priorities
==========
Every key node in Mergeable XML must have two attributes: ``priority`` and ``source``.
``source``
----------
The attribute ``source`` is a human readable name which explains where does the key node came from (for example
``default``, ``gui`` etc.) and its value is not used for anything else than troubleshooting.
``priority``
------------
This attribute contains an integer value in decimal notation. This value specifies the priority of this particular
key-value entry, which determines whether this value is going to be overwritten or not.
.. important::
Existing key node is overwritten by an incoming key node **ONLY** if the priority of the incoming key node is same or
higher than priority of the existing key node. In case the key-node IS overwritten, the incoming key node value and
attributes replace the existing key node value and attributes.
Merging
=======
In case the app stores some data as Mergeable XML, the values may never be written directly. The only way to modify this
data is by merging-in other Mergeable XML. The process of merging decides whether the values should be written or not
based on key node priorities.
Default Priorities
==================
The incoming XML to be merged in may come from various sources: provisioning from Cloud Softphone portal, response of
some provisioing web service or it may be created by the app GUI when the user saves the form. The attributes
``priority`` and ``source`` don't need to be always explicitly defined; in case they are not set, the app will deduce
them based on the origin of the data and assign a default priority:
+---------------+----------+-----------------------------------------------------------------+
| source | priority | description |
+===============+==========+=================================================================+
| default | 0 | default value, hardcoded in the app |
+---------------+----------+-----------------------------------------------------------------+
| provisioning | 10 | values coming from Cloud Softphone portal |
+---------------+----------+-----------------------------------------------------------------+
| extProv | 20 | values coming from external provisioning web services |
+---------------+----------+-----------------------------------------------------------------+
| gui | 40 | values set by end users using GUI |
+---------------+----------+-----------------------------------------------------------------+
| system | 100 | values set by system which should never be overwritten |
+---------------+----------+-----------------------------------------------------------------+
.. note::
Priorities of 100 and higher are reserved and should not be used. The app stores various persistent data using these
priorities and accidentally overwriting them may cause undefined behavior.
Localized values
================
In case of string values, it is possible to specify them either as text contents of the XML node, like shown in the
example above for ``transport`` or ``host``, or as a xml tree with multiple ``>`` nodes for different languages.
Example:
.. code-block:: xml
Nahrávaný hovor
記録されたコール
Recorded Call
The key node ``dialAction`` is a localizable node. The app will pick the string from ```` subnode which matches
the current device locale. If such node is not found, the app will take the value from ```` subnode which does
not contain a ``lang`` attribude - this node serves as a default. If such a node also doesn't exist, the app uses the
text contents of key node, just like in non-localized case.
Examples
========
Let's assume the app has an account with values and priorities as in the previous example. The user opens
"edit account" form and decides to change the ``transport`` to ``tcp``. When saving the form, the app internally
generates the following Mergeable XML:
.. code-block:: xml
tcp
It will then try to merge this document with the one stored in the app. Since the incoming priority of 40 is higher than
the stored priority of 20, the merge will be performed and the resulting document will look as follows:
.. code-block:: xml
example.com
tcp
If later, the external provisioning web service is called again and it sends the key node ``transport`` in its response,
the app will assign default priority of 20 to this node and attempt to merge it. This time, the value will not be
written, because the existing priority of 40 is higher and the user-entered value stays.
In case the provider later decides to explicitly set the ``transport`` key node priority higher, it can return the
following node in the external provisioning response:
.. code-block:: xml
url
This time, the value will be merged, because the priority is higher than the stored 40. When the user opens "edit
account" form now, he will see the ``transport`` field as read-only, because the GUI is intelligent and knows that
any new value would get a default priority of 40 and would not beat the existing priority of 50.
.. note::
In case the value is XML tree, the value is taken as a whole. If the external provisionig web service sends a node
```` in its response, the whole content of the incoming node will be stored. The merging
process is not recursive.
Filters
=======
Some values coming from provider's web services may not be merged even if the priority is set high enough. In case
the incoming value would enable functionality which is not included among the selected Cloud Softphone features on
Cloud Softphone portal, the relevant key node will be filtered out even before merging is attempted.