Executor für mehrzeilige Regeln

Häufig besteht die Notwendigkeit, mehrzeilige Regeln zu erstellen, um einen gewünschten Wert für ein Attribut zu berechnen. IBM® Verify bietet die Möglichkeit, sowohl einfache einzeilige als auch komplexere mehrzeilige Regeln zu konfigurieren.

Informationen zu Syntaxregeln für einzeilige Anweisungen finden Sie unter „Attributfunktionen “.

Elemente einer mehrzeiligen Regel

Die mehrzeilige Regel wird im YAML-Format geschrieben. Aufgrund der Formatierungsanforderungen eines YAML-Dokuments gelten bestimmte Einschränkungen. Der verwendete YAML-Parser unterstützt einen Großteil von YAML 1.1 und 1.2.

Die Bedeutung der folgenden Begriffe muss bekannt sein.
Anweisung
Eine Anweisung ist der Baustein der Regel; eine Anweisung kann unterschiedliche Typen haben. Beispielsweise wird mit der Anweisung 'return' der angegebene Ausdruck berechnet und der Ausdruck als der Regelwert zurückgegeben.
Block
Ein Block ist eine gebundene Gruppe von Anweisungen. Die Regel beginnt mit einem Block der höchsten Ebene, der als statements (Anweisungen) bezeichnet wird. Blöcke können in bestimmten Anweisungstypen vorkommen. Beispielsweise ist if.block die Gruppe von Anweisungen, die ausgeführt werden sollen, wenn die zugehörige Anweisung if.match als wahr ausgewertet wird.
Blockkontext
Ein Blockkontext ist eine Gruppe von Variablen, die in diesem Block verfügbar sind. Unterblöcke können auf den Kontext der übergeordneten Böcke zugreifen. Übergeordnete Blocke können nicht auf den Kontext der Unterblöcke zugreifen.
Ausdruck
Ein Ausdruck ist ein Snippet, das dieselbe Syntax wie einzeilige Ausdrücke verwendet. Siehe Attributfunktionen.

Unterstützte Anweisungstypen

Es werden drei Anweisungstypen unterstützt.
  • Context
  • Zurückgeben
  • Wenn

Anweisung 'context'

Eine Anweisung context dient dazu, Werte zu initialisieren und benannten Variablen zuzuordnen. Sie unterstützt zwei Operatoren.
:=
Mit diesem Operator wird eine neue Variable in dem Kontextblock initialisiert, in dem die Anweisung ausgewertet wird. Wenn beispielsweise eine Variable innerhalb eines Blocks if.block initialisiert wird, ist sie außerhalb dieses Blocks in den nachfolgenden Anweisungen nicht verfügbar.
=
Mit diesem Operator wird ein Wert einer vorhandenen Variablen zugeordnet. Die Variable kann in dem aktuellen Kontextblock oder einem übergeordneten Block vorhanden sein.
Das Format lautet context: {{varname}} := {{expression}}. Verwende `use`, context.{{varname}} um in nachfolgenden Anweisungen desselben Blocks oder in Unterblöcken darauf zuzugreifen {{varname}} .

Anweisung 'return'

Mithilfe der Anweisung 'return' wird die Regelengine angewiesen, die Ausführung zu beenden und den berechneten Wert sofort zurückzugeben.

Das Format lautet return: {{expression}}.

Anweisung 'if'

Die Anweisung if wird zum Erstellen bedingter Blöcke verwendet. Sie besteht im Gegensatz zu den beiden vorherigen Anweisungen aus mehreren Eigenschaften.

Tabelle 1.
Ihren Namen Beschreibung Format
match Bei der Auswertung dieser Bedingung als wahr wird der zugehörige Block (block) ausgeführt. match: 1 == 2
block Gebundener Block von Anweisungen, die ausgeführt werden müssen, wenn match als wahr ausgewertet wird. Ein Standard-YAML-Array von Anweisungen
elsifs Array von else-if-Bedingungen, die ausgewertet werden, wenn match nicht als wahr ausgewertet wird. YAML-Arrays, die verschachtelte Anweisungen if sind
else Block von Anweisungen, die ausgeführt werden, wenn match und alle elseifs.match nicht als wahr ausgewertet werden. Ein YAML-Array von Anweisungen

Traceprotokollierung

Eine mehrzeilige Regel kann um eine Trace-Protokollierung erweitert werden, um Debug-Protokolle zu senden. Die Eigenschaften zur Protokollierung werden ausgeführt, wenn eine Regel im aktivierten Trace-Modus ausgeführt wird. Die Trace-Protokollierung wird über die debug Eigenschaften und debugx unterstützt.

debug Anweisung

Die debug Anweisung dient dazu, den angegebenen Ausdruck auszuführen und den zurückgegebenen Wert zu protokollieren. Der Ausdruck sollte immer zu einer Zeichenkette ausgewertet werden.

Format – debug: {{expression}}

debugx Blocken

Der debugx Block besteht aus zwei Elementen: log und fields.

Ihren Namen Beschreibung Format
log Der angegebene Ausdruck wird ausgewertet und der zurückgegebene Wert protokolliert. Der Ausdruck sollte immer zu einer Zeichenkette ausgewertet werden. log: {{expression}}
Felder Benutzerdefinierte Metadatenfelder, die zusammen mit dem Protokoll gesendet werden. Wird als Map mit Schlüssel-Wert-Paaren bereitgestellt. Der Wert jedes Paares ist ein Ausdruck, dessen Ergebnis eine Zeichenkette sein muss. {{field_key}}: {{expression}}

Im entsprechenden Abschnitt finden Sie eine Beispielfunktion, die die Trace-Protokollierung veranschaulicht.

Snippets

Diese Liste der Snippets ist nicht vollständig und deckt nicht alle möglichen Verwendungen von Regeln ab. Diese Liste stellt jedoch einige Beispiele bereit, die unverändert verwendet oder erweitert werden können.

Hinweis: Da die mehrzeilige Syntax dem YAML Format folgt, ist eine korrekte Einrückung entscheidend für die ordnungsgemäße Funktion der benutzerdefinierten Regel.

Anzeigenamen des Managers abrufen

statements:
  - context: manager := user.getManager()
  - context: userExists := has(context.manager.name)
  - context: >
      givenNameExists := context.userExists
      && has(context.manager.name.givenName) 
      && context.manager.name.givenName != ""
  - context: familyNameExists := context.userExists && has(context.manager.name.familyName) && context.manager.name.familyName != ""
  - context: formattedExists := context.userExists && has(context.manager.name.formatted) && context.manager.name.formatted != ""
  - if:
      match: context.formattedExists
      block:
        - return: context.manager.name.formatted
      elseifs:
        - match: context.givenNameExists
          block:
            - if:
                match: context.familyNameExists
                block:
                  - context: managerName := context.manager.name.familyName + ", " + context.manager.name.givenName
                  - return: context.managerName
                else:
                  - return: context.manager.name.givenName
        - match: context.familyNameExists
          block:
            - return: context.manager.name.familyName
- return: string("Not Available")

Umsetzung der E-Mail-Domäne

statements:
  - context: "workEmails := has(user.emails) ? user.emails.filter(e, e.type == 'work') : []"
  - context: "workEmail := size(context.workEmails) > 0 ? context.workEmails[0].value : ''"
  - if:
      match: context.workEmail != ""
      block:
        - context: cn := context.workEmail.substring(0, context.workEmail.lastIndexOf('@'))
        - if:
            match: context.cn != ""
            block:
              - return: context.cn + "@github.com"
  - return: ""

Scoping von Variablen

statements:
    - context: ret := 3 + 4
    - if:
        match: 2 > 1block:
          - context: ret := 5
          - if:
              match: 3 > 2block:
                - context: ret = 0
    - return: context.ret

Das Ergebnis ist 7, da in Zeile 6 ret innerhalb von if.block erneut initialisiert wird. Die nachfolgenden verschachtelten Anweisungen erkennen diese Variable. Nachdem die Regelengine jedoch if.block verlässt, kann sie auf die Variable zugreifen, die in Zeile 2 initialisiert wurde.

Beispiel für die Trace-Protokollierung

Dieses Beispiel veranschaulicht die Verwendung von Trace-Logging-Anweisungen.

statements:
  - context: uid := user.id
  - context: userEmail := "user@test.com"
  - debug: '"This is an example of a trace log at time " + string(now)'
  - debugx: 
      log: '"The user id obtained: " + context.uid'
      fields:
          flow: '"login"'
          time: 'string(now)'
          userEmail: context.userEmail
  - return: context.uid  + ", " + context.userEmail

"This is an example of a trace log at time <timestamp>"Für die debug Anweisung wird der angegebene Ausdruck ausgewertet und als protokolliert.

"The user id obtained: <user id>"Für den debugx Block wird der angegebene Ausdruck ausgewertet und als protokolliert. Die folgenden benutzerdefinierten Metadatenfelder werden zusammen mit dem Protokoll gesendet.
Schlüssel Wert
"flow" "login"
"time" "<timestamp>"
"userEmail" "user@test.com"

Wichtige Einschränkungen

  • Die Variablen, die vom context-Frame initialisiert werden, sind nur innerhalb dieses Frames oder der untergeordneten Frames innerhalb dieses Frames gültig. In dem vorherigen Beispiel für eine Regel kann auf die Variable managerName nicht außerhalb des if-Frames, in dem sie initialisiert wurde, zugegriffen werden.
  • elseifs- und else-Frames können nur verwendet werden, wenn ein if-Frame auf derselben Ebene vorhanden ist.
  • Alle if- und elseifs-Frames müssen über einen Ausdruck match verfügen, der immer einen booleschen Wert zurückgibt.
  • Wenn der Regelauswertungsablauf keine Anweisung return findet, wird ein Nullwert zurückgegeben. Es werden keine Fehler ausgelöst und es wird keine Syntaxprüfung ausgeführt, um sicherzustellen, dass alle möglichen Abläufe über eine Anweisung return verfügen. Der Autor der Regel muss sicherstellen, dass alle Abläufe der Regel einen zulässigen Wert zurückgeben.