Grouping name expression

The GroupingNameExpression field of the selector is used to generate the grouping name expressions of the custom collections, for example business applications that are generated by the BizAppsAgent.

The appropriate custom collection is built for each core CI that is defined by the selector's query. The grouping name expression of the custom collection is generated for each core CI.

The advanced customization of the group can be allowed by defining the GroupingNameExpression field as a pattern that can extract attribute values from the core CIs. This pattern can also perform a regular expression matches on the core CIs instead of just providing static text names. The GroupingNameExpression supports the limited Apache Velocity syntax to provide such flexibility in defining grouping name expressions of the generated custom collections.

Tip: For details about model objects, for example their attributes and relationships, see the CDM documentation that is shipped with TADDM. It is in the cdm/datadictionary/cdm/misc/CDM.htm directory.
There are two predefined variables in the GroupingNameExpression pattern:
$coreCI
This variable represents the core configuration item that is being processed by the BizAppsAgent. It can be used to extract attributes of the core CI. For example, $coreCI.displayName gets the displayName attribute from each core CI and puts its value into the generated grouping name expression.
$utils
This variable represents the utilities available in patterns. The following utility methods are available:
  • $utils.regex(inputText, regexPattern1 [, ..., regexPatternN]) - a method that extracts the part of the inputText attribute by using regular expression patterns that are defined in the regexPattern1..N attributes. Extraction is performed by using a regular expression matching groups. Therefore, regexPattern1..N attributes must define at least one matching group. Regular expression patterns without any matching groups are invalid and result in an error.
    Note: Not matching groups, for example "abc(?:\d+)", are ignored. Therefore, this example is invalid, as it does not contain at least one matching group.

    The contents of the first matching group that successfully matched the input text is selected as a result. For example, for the input text "abc-1234-def" and pattern "[A-Z]+-(\d+)|[a-z]+-\d+-(\w+)", the second matching group (\w+) that captures the "def" substring is selected because the first one does not match the input.

    The regexPattern1..N regular expression patterns are matched in sequence 1 to N until the first match is found.

  • $utils.or(expression1, ..., expressionN) - a method that evaluates all expressions and selects the first result of the expression that is not null as its result.

    For example, if the $coreCI.description property has no value and the $coreCI.name property is set to a valid value, then utils.or($coreCI.description, $coreCI.name) returns the result of the $coreCI.name expression as its result. The error that the $coreCI.description property is not available is not reported, as it would be, if only the $coreCI.description was used.

  • $utils.toUpper(inputText) - a method that converts the inputText attribute value to uppercase characters.
  • $utils.toLower(inputText) - a method that converts the inputText attribute value to lowercase characters.
  • $utils.trim(inputText) - a method that removes all leading and trailing white space characters from the inputText attribute value.
  • $utils.replace(inputText, pattern, substitute) - a method that replaces all substrings of the inputText attribute that match the pattern with substitute. The pattern attribute is a regular expression pattern, which can include matching groups. The substitute attribute can reference the matching groups that are defined in the pattern attribute by using $1 for the first matching group, $2 for the second matching group, and so on.
    Note: If the dollar sign ($) or backslash (\) are used in the replacement string, they must be escaped by adding another backslash as a prefix to the string. For example, in the $utils.replace($coreCI.name, "some pattern", "abc\$123") invocation, the substitute is a static text "abc$123" that includes the dollar sign because the dollar sign was escaped by using the \$ combination (therefore $123 does not reference the matching group 123). The substitute texts that contain the dollar sign or backslash alone, for example "abc$def" or "abc\def", are invalid because the dollar sign and backslash were not escaped by adding the backslash as a prefix. In this case, the valid substitute texts are "abc\$def" and "abc\\def".

Examples

  • For a grouping pattern with the following elements:
    • hierarchyType: BusinessApplication,
    • selector with MQL query: SELECT * FROM Database,
    • GroupingNameExpression: $coreCI.displayName,
    the generated grouping name expression is the value of the displayName attribute of each core CI. If display names are unique, separate business applications with grouping name expression set to the display name of that core CI are created for every core CI selected by the selectors' query.
  • For a grouping pattern with the following elements:
    • hierarchyType: BusinessApplication,
    • selector with MQL query: SELECT * FROM J2EEApplication WHERE name contains '_EDT-',
    • GroupingNameExpression: eDayTrader,
    a single business application with the eDayTrader grouping name expression that contains all core CIs and their dependent objects is created.
  • For a grouping pattern with the following elements:
    • hierarchyType: BusinessApplication,
    • selector with MQL query: SELECT * FROM Database WHERE name starts-with 'prod_',
    • GroupingNameExpression: BizApp-${utils.regex("${coreCI.name}", "prod_(.*)")}-${coreCI.label},
    and for the core CI with the "prod_EDT1" name and the "trader1" label, the generated grouping name expression is BizApp-EDT1-trader1.

    All partial custom collections that are generated for core CIs with a matching name, for example EDT1, and a matching label, for example trader1, are assigned into a single business application collection with grouping name expression, for example BizApp-EDT1-trader1. It allows for dynamic assignment and grouping of configuration items and their related objects to business applications based on any matching attribute combinations.

Apache Velocity syntax

The GroupingNameExpression pattern supports limited Apache Velocity syntax and is validated during creation. The following validations are enforced:
  • No #include or #parse directives are allowed in the pattern.
  • $coreCI and $utils variables are predefined and ready to be used in the pattern, but they cannot be redefined. Other variables can be defined and used in the pattern by using the #set directive.
  • On the $coreCI variable, only property access is allowed. No method calls, for example, getters and setters, are allowed. The result of property access to the $coreCI variable must be a string or other simple data type, like Boolean, int, long, float, double. Especially, it cannot be a model object or array. Accessing the $coreCI properties that are model objects or arrays to get their properties or elements is allowed, when the result is not a model object or array.
    Examples:
    • $coreCI.name is allowed.
    • $coreCI.OSRunning.name is allowed. It is used to access OSRunning, which is a model object of the OperatingSystem type, to get the name property.
    • $coreCI.OSInstalled[1].name is allowed. It is used to access the second element of an array of OperatingSystem elements to get the element name property.
    • $coreCI is not allowed. $coreCI is a model object.
    • $coreCI.OSRunning is not allowed.
    • $coreCI.OSInstalled is not allowed. It results in an array of model objects.
    • $coreCI.OSInstalled[1] is not allowed. The result of OSInstalled[1] is a model object OperatingSystem.
    • $coreCI.setName("test") is not allowed,
    • $coreCI.getName() - is not allowed.
    • $coreCI.hasName() - is not allowed. However, the equivalent construct #if ($coreCI.name) ... #end is allowed. Additionally, $utils.or($coreCI.name, $coreCI.otherProperty, ...) can be used to select the first property that exists and that is set.
    • $coreCI.test() - is not allowed. Any other method call is not allowed as well.
  • On the $utils variable only defined method calls are allowed:
    • $utils.regex(inputText, regexPattern1 [, ..., regexPatternN])

      Null values are not allowed on the regexPattern1..N attributes. Each regexPattern must define at least one matching group. The inputText attribute can be null, when the $utils.regex invocation is not the last invocation in chain resulting in insertion of its result into the final text. For example, if such $utils.regex call trying to access not set $coreCI property is nested inside the $utils.or invocation, it does not generate error when $utils.or is able to select any other expression value that is not null as a result. In all other cases, such $utils.regex call results in an error.

    • $utils.toUpper(inputText)
    • $utils.toLower(inputText)
    • $utils.trim(inputText)
    • $utils.replace(inputText, pattern, substitute)

      The pattern and substitute attributes must be valid strings that are not null. The pattern attribute must be a valid regular expression pattern. The substitute attribute must be a valid substitution or replacement pattern with appropriate escaping of the dollar sign ($) and backslash (\), and the appropriate usage of matching groups.

    • $utils.or(expression1, ..., expressionN)

      Expression attributes can be null, when the whole expression that involves the $utils.or invocation evaluates to a value that is not null.

      The following list contains exemplary expressions, where the $coreCI.name property is valid, the $coreCI.description property is not set, and the $coreCI.instanceID property does not exist. The $coreCI.instanceID property can be a property that does not exist in case when the current $coreCI is of the ComputerSystem type, which does not have the instanceID property (the instanceID property is a valid property of AppServers, and so on).
      • $utils.or($coreCI.description, $coreCI.instanceID) - not valid. It results in an error because it evaluates to a null value.
      • $utils.or($coreCI.description, $coreCI.instanceID, "default") - valid. Even though the description property is not set and the instanceID property does not exist, the last attribute is a static text "default" and the whole $utils.or invocation successfully evaluates to this value.
      • $utils.or($coreCI.description, $coreCI.instanceID, $utils.name) - valid. Even though the description property is not set and the instanceID property does not exist, the name property is valid and the whole $utils.or invocation evaluates to a valid value of $coreCI.name.
      • $utils.or($utils.or($coreCI.description, $coreCI.instanceID), "default") - valid. Even though the inner invocation $utils.or($coreCI.description, $coreCI.instanceID) evaluates to an invalid value, the outer $utils.or invocation, and at the same time the whole expression, evaluate to a valid value "default".
      • $utils.or($utils.toUpper($coreCI.description), $utils.regex($coreCI.instanceID, "prod_(.*)", $utils.toLower($coreCI.name)) - valid. Even though the $utils.toUpper($coreCI.description) and $utils.regex($coreCI.instanceID, ...) invocations are not valid, the outer $utils.or invocation, and at the same time the whole expression, evaluates to a valid value of $utils.toLower($coreCI.name).
      Examples
      • BizApp-$utils.or($utils.regex($utils.toLower($coreCI.label,) "appserver-(.+)"), $regex($coreCI.description, "application server number (\d+)"), "default")
        • For the { label="AppServer123", name="CS-123", description="..." } core CI, the result is "BizApp-123" - extracted from $coreCI.label attribute.
        • For the { label=null, name="CS-123", description="This is an application server number 123. Installed mod...." } core CI, the result is "BizApp-123" - extracted from $coreCI.description attribute.
      The following $utils.or method calls can be nested:
      • BizApp-$utils.or($utils.or($coreCI.name, $coreCI.label, $utils.regex($coreCI.description, "name: (\S+)")), "default")
      • BizApp-$utils.or($utils.regex($coreCI.name, "prod_(.*)|test_(.*)"), $utils.regex($coreCI.keyName, "systemA-(\\d+)|systemC-(\\d+)|system?-?-(.*)"), "default")
      • BizApp-$utils.or($utils.regex($coreCI.name, "test_(.*)", "test1_(.*)"), $utils.regex($coreCI.keyName, "prod1_(.*)", "prod_(.*)"), "default")
      • BizApp-$utils.or($coreCI.primarySAP.fqdn, $coreCI.primarySAP.primaryIpAddress.dotNotation, $coreCI.primarySAP.primaryIpAddress.byteNotation, $coreCI.primarySAP.primaryIpAddress.stringNotation, "unknown")
      • Equivalent to the preceding one #set($ip = $coreCI.primarySAP.primaryIpAddress)BizApp-$utils.or($coreCI.primarySAP.fqdn, $ip.dotNotation, $ip.byteNotation, $ip.stringNotation, "unknown")