Skip to content

Indirect expression

MaartenHilferink edited this page Jun 25, 2026 · 10 revisions

In modelling the same modelling logic is often applied to different (sets of) parameters. A model might for instance be calculated for multiple years, regions etc.

In these cases you would like to configure the model logic once. For this purpose, the GeoDMS uses the concept of meta modelling, with indirect expressions.

An indirect expression is defined as an expression in which one or more elements are based on the contents of other items in the configuration. The resulting direct expressions are generated using the indirect expression logic and the items used in the configuration.

syntax

attribute<bool> total (rdc_100l) := ='or('+asItemList(ggEndogenous/Name)+')';

An indirect expression always starts with an equals sign (=) character. In these expressions two elements are distinguished:

  1. fixed, non generated elements, configured between single quotes. In the example the or function will be part of the evaluated expression.
  2. generated elements, that need to result in a string. In the example the function asItemList will be evaluated and the results of this evaluation will be part of the evaluated expression.

two step processing

An indirect expression is processed in two steps:

  1. First the indirect expression is evaluated to a direct expression. In the example this evaluation results in the expression: "or(woon_bc, woon_cd,..., agr_kweekerij)". Evaluated expressions are visible in the GeoDMS GUI, Detail Page > General > CalculationRule.
  2. The direct expression is calculated.

Indirect expressions are a powerful feature for the configuration of generic modelling logic. But be cautious with the indirect expressions, as they tend to make configurations more difficult to understand and to debug (see also Error-tracking-in-indirect-expressions)

use in conditions

Indirect expressions can be used to configure a condition (iif or switchcase) with the following advantages:

  1. In the evaluation of an iif function, both the then and else subexpressions are calculated. If an indirect expression is used, the resulting expression will only contain the then or else subexpression, the other statement does not have to be calculated. The same holds for the cases of a switchcase function: only the selected case ends up in the evaluated expression.
  2. Some functions like GeoDMSVersion are session-specific. This means all results of expressions directly or indirectly using the results of an expression in which these functions is used, will not be stored persistently and need to be recalculated each time the application is rerun.

Be aware that the condition used to select a branch must be uniform for the whole item, i.e. a void parameter. An indirect expression is only allowed to evaluate to a single calculation rule (one direct expression). A condition with a non-void domain unit would imply a different branch, and thus a different calculation rule, per domain element, which an indirect expression cannot represent. For conditions that vary per domain element, use a regular iif / switchcase (in which all branches are calculated).

example

The following example only calculates the (time consuming) item that the selected case refers to. The condition is configured as a set of void parameters (the file checks), so it is uniform for the whole item:

parameter<string> phase_input_expr :=
    switch(
        case(python_output_filename_exists, 'dummy_error_code'),
        case(BAG_output_filename_exists,    'Python_script_error_code_bestaandedata'),
        'Python_script_error_code'
    );

parameter<uint32> phase_input := =phase_input_expr;

The = in the calculation rule of phase_input turns the contents of the string parameter phase_input_expr into the (indirect) expression to evaluate.

readability and debugging

Indirect expressions tend to make configurations harder to read and debug (see also Error-tracking-in-indirect-expressions). Two practices help:

  1. Lift the indirect expression into a separate string parameter (e.g. phase_input_expr above) and evaluate it in a second item with the = prefix. The intermediate string parameter is not strictly necessary, but it makes the generated expression directly inspectable in the GeoDMS GUI, Detail Page > General.
  2. Give each part of the condition its own named parameter, so the evaluated rule and each individual test can be read and checked on their own:
parameter<bool> python_output_filename_exists := ExistingFile('', python_output_filename) == Expand(., python_output_filename);
parameter<bool> BAG_output_filename_exists    := ExistingFile('', BAG_output_filename)    == Expand(., BAG_output_filename);

parameter<string> phase_input_expr :=
    switch(
        case(python_output_filename_exists, 'dummy_error_code'),
        case(BAG_output_filename_exists,    'Python_script_error_code_bestaandedata'),
        'Python_script_error_code'
    );

parameter<uint32> phase_input := =phase_input_expr;

be aware

The evaluation of indirect expressions is executed when the meta/scheme information is generated in the GeoDMS GUI. If for this evaluation (large) primary files are read, this becomes times consuming. Expanding tree items in the treeview becomes slow. Therefor we advice to use the contents of large primary data file (or complex calculations) as little as possible in indirect expressions.

Clone this wiki locally