Configuration Resolver - Concepts
Overview
The purpose of the plugin is to allow to set up a specific configuration for a Wedia portal application, by overriding a basic configuration provided by the product.
The base of the configuration is a JSON file. Any element of this JSON can be overriden in a folder, through a tree of files and folders that correspond to the tree of the base JSON. Multiple folders can be added to redefine the configuration redefined by the previous folders.
Mappings
A configuration is thus defined by a series of files that will redefine the basic configuration successively, in order to obtain a final configuration, the fusion of the whole.
This series of folder constitutes a path designated by a unique identifier. A client application will retrieve its final configuration via this ID. Mappings define the correspondence between IDs and paths. The configuration of mappings is done in the plugin settings.
A mapping is defined by
a name (or ID): it is by this name that an application will request the necessary configuration
a path: the path defines a set of locations in which the different files constituting the final configuration will be stored.
Mapping path
It is a string of characters formed by subpaths separated by the arobas character (@
).
a subpath can be static: a simple name (it is ultimately a part of a filename and therefore must contain only characters allowed for a filename except for arobase)
a subpath can be dynamic: a dynamic subpath begins with the colon character (
:
) followed by a processor (or postprocessor) namea subpath can start with a dollar character (
$
) (we speak then of restarting subpath)
The general principle of the configuration evaluation is that this path will determine the different files that will be used to build the final configuration.
The first subpath will be used to determine the basis of the configuration: it is the basic configuration file provided by the product for a given application (see Configuration Resolver - Concepts | Base ). This is a JSON file that describes the basic configuration of the product.
Then we join the first subpath with the second one by separating them with the arobas character (
@
). This is a new location in which to look for files involved in the final configuration.Then we assemble the first three subpaths in the same way, and so on until the end.
When a subpath refers to a processor, the value of the subpath is dynamically calculated by this processor, and this value is used to build the path of the location where we will look for the configuration files
When a subpath is restarting, a location path built with this subpath starts with this subpath
Example 1 - a path consisting only of static subpaths
app@config@project
the base is
app
the successive paths where we will look for the configuration files are
app.xjson
orapp.json
(the base)app@config
first layerapp@config@project
second layer
Example 2 - a path referring to a processor with identifier proc
, which will generate the values foo
, bar
and baz
app@config@:proc
the base is
app
the processor is
proc
(identifier preceded by a colon)the successive paths where we will look for the configuration files are
app.xjson
orapp.json
(the base)app@config
first layersecond layer, for the processor value corresponding to the query context (for example:
bar
)app@config@bar
Example 3 - restarting path
app@config@project@$picker@project
the base is
app
the successive paths where we will look for the configuration files are
app.xjson
orapp.json
(the base)app@config
first layerapp@config@project
second layerpicker
third layer (restart path to configuration container root)picker@project
fourth layer
Base
for example, if path is
app@config
, the base isapp
;for example, if path is
app
, the base isapp
;for example, if path is
app@config@project
, the base isapp
.
Processor (column character)
A processor is a component that converts connection context into value. For example, in the connection context, the role of the surfer can be converted into a value to select a specific layer: if the role is 4 for example, we will use base@admin@project
and for the other roles, base@common@project
.
A processor is indicated in a mapping path by preceding it with a colon (:
). For example, if the processor is called role: base@:role@project
.
Path restart (dollar character)
A path is associated with a mapping: some layers can be shared between mappings. For example, we can have a mapping for portal, such as starterkit@portal@project
, and another mapping for wedia config such as starterkit@wediaconfig@project
, such that the project properties are the same for both mappings. Instead of making two folders starterkit@portal@project
and starterkit@wediaconfig@project
that would contain the same files, we can use the cut/restart system characterized by the dollar ($
) character in the path definition:
mapping
portal = starterkit@portal@$project
mapping
wediaconfig = starterkit@wediaconfig@$project
In the end the files will be (for both mappings):
starterkit.xjson
, the common basestarterkit@portal
, the layer dedicated to Portalstarterkit@wediaconfig
, the layer dedicated toWedia Config
and
project
, the common layer
It is of course possible to combine the dollar
and the colon
: for example starterkit@portal@$project@$:role
.
Override a value in the configuration
To override a property of the basic JSON, you just need to have a file tree corresponding to the path of the property to replace, or to add. Folders or files represent properties (or array indexes), and scalar values are the contents of files, while objects and arrays are folders.
The suffix of the file is important to determine how its value will be read:
json
: json scalar values (must be JSON parsable)txt
ortext
: string value, mimetype text/plainhtml
orhtm
: string value, mimetype text/html
For example, we have this base:
{
"a": {
"d": {
"e": 1,
"f": 2
},
"g": {
"h": 1,
"i": 2
}
},
"b": {
"j": {
"k": 1,
"l": 2
}
},
"c": {
"m": 1
}
}
With the following file tree:
folder a
(path $.a
)
folder d
(path $.a.d
)
file f.json
= "replace 2"
file z.json
= 4
You will obtain finally the following JSON:
{
"a": {
"d": {
"e": 1,
"f": "replace 2",
"z": 4
},
"g": {
"h": 1,
"i": 2
}
},
"b": {
"j": {
"k": 1,
"l": 2
}
},
"c": {
"m": 1
}
}
When you replace an object, or an array, you dont replace the whole object or array (above, the property $.a.d.e
=1
has not disappeared)
XJSON
If it is quite obvious to redefine the property of a JSON object, to replace a value, array values cannot be completely redefined: in particular, it is impossible to make insertions. The XJSON format is a JSON-based format where arrays are modeled by objects: the property name is terminated by the []
characters and the properties in the object represent indexes.
The following table for example,
{
prop: [ "a", "b", "c" ]
}
will become
It is now easy to add a value, x
at the end, y
between b
and c
, and even z
before a
, and then replace b
by t
:
The final configuration will be
XJSON strict versus lenient
strict XJSON must not contain any array
lenient XJSON allows arrays. In a process of overwritting, an array is converted in object with the following law to define index
Constants.DEFAULT_DISTRIB_OFFSET + Constants.DEFAULT_DISTRIB_INDEX*index
whereindex is the index of array item
Constants.DEFAULT_DISTRIB_INDEX
the step (default is 1000)Constants.DEFAULT_DISTRIB_OFFSET
the offset (default is 1000)this value is finally left padded with
Constants.NUMBER_OF_ZERO_IN_INDEX
zeros (default is 9)
Examples:
Index in array | Formula | Property in XJSON array object |
---|---|---|
0 |
| 000001000 |
1 |
| 000002000 |
2 |
| 000003000 |
9 |
| 000009000 |
10 |
| 0000010000 |
Delete a value
We have seen how to replace or add properties but sometimes it is necessary to delete them. To delete a property user an empty file with suffix delete
.
By example, this base:
With this file tree:
folder a
(path $.a
)
folder d
(path $.a.d)
file f.delete
will give you finally the following JSON:
If you need to delete an object (or an array) completely, you can also use the delete
extension:
folder a
(path $.a
)
file d.delete
folder d
(path $.a.d)
file z.json
= 1
will give you finally the following JSON:
All the properties contained in $.a.d
, e
and f
have been deleted.
Property names versus file names
Not all characters that can be used in property names can be used in file names, and some concepts are determined by reserved characters. It is therefore not possible to directly transpose property names in json into file names. Certain file naming rules are therefore used.
See details here.
Configuration Container
A container is any location intended to store files involved in the final configuration.
There are three types:
Bases, which are files containing the product configuration
these files are stored in plugins, by default in their/config/config_resolver/bases
folderConfiguration containers, which are folders containing project configuration file trees.
These trees are stored in plugins, by default in the/res/config_resolver/configs folder
Client storage, which is a protected folder in SAN (
appconfigs/config_resolver/configs
) that stores client configuration files (or at least those created by the Wedia-Config Application).
Base Location
For a mapping, a base location designates the plugin (and possibly the folder within this plugin) that will contain a base.