Rule Engine

Rule Engine Overview

The N2SVCD distribution includes a generic rule-matching library that can be used to select one or more matching rules from a configuration item, based on input values from the appropriate N2SVCD LogicApp service.

Additionally, it offers a mechanism for specifying and using arbitrary “variables” within the context of a service’s application.

Integration

Rule engine functionality can be included by any LogicApp script as a standard require, e.g.:

local rule_engine = require ("n2.rule_engine")

In the above example, the LogicApp definition should include the N2SVCD Lua library location, i.e.:

../lua/lib/?.lua

Rulesets are Lua arrays with each element specifying a single rule, e.g.:

array = {
  { param1 = "1", param2 = "2" },
  { param1 = "3", param2 = "4" }
}

Alternately, rulesets with only a single rule may be specified in shorthand, e.g.:

shorthand = { param1 = "5", param2 = "6" }

These may be defined natively or passed in from N2SVCD LogicApp globals configuration, e.g.:

    <global name="SOME_ARRAY" type="array">
        <thing id="thing1" value="1"/>
        <thing id="thing2" value="2"/>
        <thing id="thing3" value="3"/>
    </global>

    <global name="SOME_SHORTHAND" id="thing4" value="4"/>

… will be loaded in the LogicApp as:

SOMEARRAY = {
  { id = "thing1", value = "1" },
  { id = "thing2", value = "2" },
  { id = "thing3", value = "3" }
} 
SOME_SHORTHAND = { id = "thing4", value = "4" }

Both formats will be accepted by the rule engine for any rule functions, including variable definition.

Rule Engine Functions

All rule engine functions are pure Lua and synchronous.

Contexts

Rule functions expect two contexts to be provided as Lua tables, the input context and the service context.

Both are completely free-form, but are separated as services will usually treat the input context as read-only (i.e. the message as received from the network) while using the service context for temporary transaction storage.

The context to search may be specified in selector rule parameters or values by using input. or service. as prefixes. If no prefix is specified, input. is assumed.

Note that variables are stored in the service context when initialised by the rule engine.

Rule Selection

Selector Rules Overview

The primary purpose of the rule engine is to provide a generic framework to allow selection of a value or values based on arbitrary input data from a list of Selector Rules.

Rules are traversed in order and matched based on selectors to raw or derived fields in the input data for the LogicApp service or from configured variables.

Selector Rules Configuration

Rule definition is generally for an application-specific purpose, and relies on protocol-specific input data.

Each rule object for IDP selection can support the following attributes:

Attribute Type Can Invert? Description
literal String No [Conditional] The literal value to return when the rule is selected. One of literal, source, or from_var must be present for each rule.
source String No [Conditional] A field from the protocol- or service-specific context to return as the value when the rule is selected. Multiple fields may be separated by a comma, and will be concatenated (if populated). One of literal, source, or from_var must be present for each rule.
from_var String No [Conditional] A variable name to return the value of when the rule is selected. Multiple tag names may be separated by a comma, and will be concatenated (if populated). One of literal, source, or from_var must be present for each rule.
r_index Integer No For source and from_var source selection, r_index can be used to specify the starting index for value retrieval. Positive values count from the start of the string (zero-indexed), and negative values count from the end. Used in conjunction with r_len to provide any substring of the selected value, including prefix or suffix.
(Default: 0, copy from the start of the string)
r_len Positive Integer No For source and from_var source selection, r_len can be used to specify the returned length of the selected value. Used in conjunction with r_index to provide any substring of the selected value of the selected value, including prefix or suffix.
(Default: the selected value’s remaining length after r_index has been applied)
var String No [Conditional] Selector for a variable name to match the value for. If var is present, value must also be present.
var_prefix String No [Conditional] Selector for a variable name to match the value prefix for. If var_prefix is present, value must also be present.
var_x String No [Conditional] As for var, but with x representing a unique pairing, e.g. var_12 or var_abc. A matching value_x must also be present with the appropriate suffix.
var_prefix_x String No [Conditional] As for var_x, but for matching against the value prefix. A matching value_x must also be present with the appropriate suffix.
value (various) Yes [Conditional] The string or integer value to match against during rule selection. Required when either var or var_prefix is present.
value_x (various) Yes [Conditional] As for value, but with x representing a unique pairing, e.g. value_12 or value_abc. A matching var_x or var_prefix_x must also be present with the appropriate suffix.
(other available fields) (various) Yes Any number of service- or protocol-specific fields.

Values of source fields or the field names for the other available fields must be specified in full dot-notation form, e.g. input.initialdp_args.serviceKey. Either input or service may be prefixed in order to select the appropriate context to match on. If neither input nor service is specified, input is used as the default context.

Note that it is not required that Selector Rules are in elements called rule. The element name is ignored when parsing rulesets.

Each rule must provide a value, either as a literal or copied from a context or variable field. All selectors in a rule must match in order for the rule to be selected. If no selectors are present (e.g. only a literal is configured), the rule will always match, acting as a catch-all.

Returning a Substring

The r_index and r_len fields can be specified in order to return only a substring of the found value.

The field r_index is zero-indexed, with the following semantics:

The r_len value indicates how many characters at most should be returned, regardless of the index position.

Examples using the source value abcde:

r_index r_len Result
(not specified) (not specified) abcde
0 (not specified) abcde
3 (not specified) de
-3 (not specified) cde
(not specified) 1 a
0 1 a
3 1 d
-3 1 c
Selector Inversion

Some fields in selector rules may have their match be made inverted. To do this, add the character ! to the start of the match value.

If the string to be matched starts with an exclamation mark, add an additional !, i.e. !! for a normal match and !!! for an inverted match.

Some examples of using and not using inversion:

Rule Functions

Get Source, Get Rule, Get All

The three core functions for rule selection are rule_engine.get_source, rule_engine.get_rule, and rule_engine.get_all. These functions all search the provided ruleset for matching according to the supplied input and service contexts.

These functions all take the following parameters:

Attribute Type Description
input_context Table Required The received input context object from the underlying service.
service_context Table Required The service’s context object.
ruleset Table Required The array of rules to analyse. Each rule should be a hash of possible keys and values that are used to match against the given arguments. For selection of sub-hashes, use dot notation.
ignore_keys Table An optional array of additional keys to ignore when matching rules.

These functions return

A Lua error will be thrown if a processing failure occurs.

Validate Rule Variables

The function rule_engine.validate_rule_variables determines if the provided rule has internally-consistent variable definitions. It does not check whether variable definitions are valid or populated within the service context.

This function takes the following parameters:

Attribute Type Description
rule Table Required The configured rule to validate.

This function does not return anything.

A Lua error will be thrown if a processing failure occurs or if the rule’s variable definitions are not internally-consistent.

Validate And Prepare Boolean Keys

The function rule_engine.validate_and_prepare_boolean_keys validates that any provided boolean keys in a rule are valid. Any keys not present are set to their default value.

This function takes the following parameters:

Attribute Type Description
rule Table Required The configured rule to validate.
keys Table Required A table of keys to check in the format { <key name> = <key default value, either true or false>, ... }

This function does not return anything. The rule will be updated in-place.

A Lua error will be thrown if a processing failure occurs or if the rule’s variable definitions are not internally-consistent.

Rule Contains Source

The function rule_engine.rule_contains_source checks if a configured rule contains a key from the available core value source types.

This function takes the following parameters:

Attribute Type Description
rule Table Required The configured rule to validate.
allowed Table An optional array of additional allowed source keys.

This function returns true if the rule contains an allowed source key, otherwise false.

Variable Management

Variable Overview

The rule engine can be used to store values in “variables” within the service context for later use. Variables are referred to by a freeform name, and can hold string or integer values, either read from received messages from the network or configured as literals.

Variables may be referred to by other rule engine configuration as required to influence rule selection behaviour.

Once populated, variables are available within the provided service context under the sub-object vars. These can be read directly as required. They can also be written to, but that is not a usual use case.

The rules engine sets variable values via the use of Rule Selection to apply the appropriate rule for each variable. Each variable may be given a maximum of one value from its list of rules; as soon as a match is found, the remaining rules for that variable are not used.

Variables are configured as a LogicApp service global named VARIABLES. A simple variable configuration of a LogicApp instance receiving input for mobile calls from the N2SCP Logic Hand-Off Application might be:

<application name="Logic" module="LogicApp">
    ...
    <config>
        <services>
            <service module="LhoScpApp::LhoScpLuaService" ...>
                ...
                <globals>
                    <global name="VARIABLES" type="array">
                        <variable name="msc" mandatory="1">
                            <rules type="array">
                                <rule source="initialdp_arg.mscAddress_digits" />
                            </rules>
                        </variable>

                        <variable name="vlr" mandatory="0">
                            <rules type="array">
                                <rule source="initialdp_arg.locationInformation.vlrNumber_digits" />
                            </rules>
                        </variable>

                        <variable name="network" edr="NET" mutable="1">
                            <rules type="array">
                                <rule input.ssp_inap="!camel" literal="home"/>
                                <rule var_prefix="vlr" value="1500" literal="home"/>
                                <rule var_prefix="vlr" value="1" literal="national_roaming" />
                                <rule service.forwarding="true" var_prefix="msc" value="1500" literal="home"/>
                                <rule service.forwarding="true" var_prefix="msc" value="1" literal="national_roaming" />
                                <rule literal="roaming" />
                            </rules>
                        </variable>

                        <variable name="location" mandatory="1" mutable="1">
                            <rules type="array">
                                <rule input.ssp_inap="cs1" service.forwarding="false" source="locationNumber_digits" />
                                <rule service.forwarding="false" from_var="vlr" />
                                <rule service.forwarding="true" from_var="msc" />
                            </rules>
                        </variable>
                    </global>
                    ...

This variable configuration sets the following:

Variables are assigned their values in the order configured. Later variable rules may therefore refer to previous variable values if required as shown with the network variable definition above.

Variable names and their values may also be written to EDRs automatically by LogicApp services as part of variable function execution. Only variables with a defined edr parameter will be written.

All variables defined must have a name parameter applied, and must contain at least one rule. Note that no catch-all rule is required for variables; if no rule applies no value will be given to the variable (and it will not be created).

Variable Configuration

All variable configuration is part of the LogicApp service’s VARIABLES global. Each variable may have the following attributes:

Attribute Type Description
name String Required The name of the variable. Must be unique.
mandatory Boolean Whether the variable is required to be populated or not. If no suitable value can be found for a variable marked as mandatory, an error will be raised. Default = 0, variable is not mandatory.
mutable Boolean Whether or not a variable value selection may be updated on a subsequent variable population attempt. Default = 0, don’t allow update.
edr String An EDR key to write the variable’s value to. Will be converted to uppercase automatically. If not specified, the variable will not be written to the EDR.

A variable must then contain a rules child parameter with its type explicitly set to array. Within the rules parameter, Selector Rules can be specified in order to set the variable’s value.

Variable Functions

Set Variable Values

The function rule_engine.set_variable_values is used to populate the service context variables from received input. It will also validate the global VARIABLES configuration if not already done.

This function takes the following parameters:

Attribute Type Description
input_context Table Required The received input context object from the underlying service.
service_context Table Required The service’s context object.
edr Table Required The service’s current EDR keys and values.

This function does not return anything. Variable values and EDR fields are updated directly within the service context or EDR table.

A Lua error will be thrown if a processing failure occurs.