.. _Configuration: Configuration ============= When you start a command line tool, you can supply it with one or more configuration destinations. The configuration is written in `JSON `__. Reading ------- Hierarchy ********* The configuration follows a hierarchy that is separated by dots (``.``) in the names of the keys. The hierarchy is inferred from the file system and the structure of the JSON in the files. For example, assume you supply the config destination ``config/local/`` and there is a file ``config/local/some/path/Test.json`` and it contains the following content:: { "some_key": { "other_key": { "the_answer": 42, "the_question": ["life", "universe", "everything"] } } } In this case, the config key ``some.path.Test.some_key.other_key.the_answer`` will be read and set to ``42`` and the key ``some.path.Test.some_key.other_key.the_question`` will contain a list of strings as shown. A config destination can contain the special file called ``parent``. It should consist of a single line giving a path (absolute or relative to the current destination) to include. This means the contents of the given destination will be treated as if they were present in the current destination. Additionally, the parent destination will be read first which is important for cascading (see below). Cascading ********* The structure of the configuration makes it possible (and actually good and common practice) to split a config object across multiple locations. For example your config destination may have a file ``Test.json`` that contains :: { "field_1": 42 } but also reference a ``parent`` directory that also has a file ``Test.json`` that contains :: { "field_2": 23 } In effect, both ``Test.field_1`` and ``Test.field_2`` are correctly read. By default, we use this technique to separate * configuration specific to an installation, which includes * configuration specific to a robot model, which includes * generic configuration. This makes the configuration easy to maintain. Given the rules for the hierachy and for parent destinations, it is very much possible to specify the same key multiple times. In that case **the key that is read last overwrites any previous one of the same name**. In particular, a destination always overrides its parent. Appending ********* It is also possible to append values to an array, by adding a ``+`` to the variable name as such: :: { "array": [1, 2, 3] } { "array+": [4, 5, 6] } The resulting ``array`` config value will be ``[1, 2, 3, 4, 5, 6]``. Command line ************ You can also supply configuration on the command line. For example, to set ``MyModule.max_velocity`` to ``5``, append ``--MyModule.max_velocity 5`` to the command line. Values are read as JSON objects. Make sure to use the correct quoting according to the shell you use. When setting a boolean value to ``true``, you can omit the value and just give the key. Arrays and objects can be provided on the command line as follows: :: command --array [1, 2, 3, 4] --object {"field": 1234, "array": ["a", "b", "c"]} Config keys given at the command line are read as the ultimate last ones, so they override any previous keys with the same names. This is useful for testing out certain values without constantly having to edit files. Assignment ---------- While some config keys are read explicitly by the application, most of the assignment happens automagically. Modules ******* A module that is started with the name ``MyModule`` will automatically be assigned all configuration below the ``MyModule.`` key. From then on it behaves like a class (see below). Classes ******* If a configuration key is applied to an instance of a VNX class, the members of the class are assigned the subkeys where the names match. For example if you have an object of the class :: class Test { string name; int value; vector numbers; Test2 other_one; } and you assign it the config :: { "name": "Picard", "value": 1234, "numbers": [1, 2, 3, 4], "other_one": { "what": "ever" } } then all the fields get assigned the config key with the matching name. Notice that ``other_one`` is another object which will get the same treatment recursively with the embedded config object. Fields without a matching config key are default initialized and spare keys without a matching field are silently ignored.