Executor de regra multilinhas

Há situações em que é necessário construir regras multilinhas para calcular um valor desejado para um atributo. IBM® Verify permite configurar tanto regras simples de uma linha quanto regras mais avançadas de várias linhas.

Para regras de sintaxe de linha única, consulte Funções de atributos.

Elementos de uma regra multilinhas

A regra multilinhas é escrita no formato YAML. Ela é restrita de acordo com as necessidades de formatação de um documento YAML. O analisador YAML utilizado suporta a maior parte do conteúdo de YAML 1.1 e 1.2.

É importante entender os termos a seguir.
Instrução
Uma instrução é o bloco de construção da regra e pode ser de diferentes tipos. Por exemplo, a instrução de retorno calcula a expressão que foi fornecida e retorna a expressão como o valor de regra.
Bloco
Um bloco é uma coleção limitada de instruções. A regra começa com um bloco de nível superior chamado statements. Os blocos podem existir dentro de certos tipos de instrução. Por exemplo, if.block é a coleção de instruções a serem executadas quando a instrução if.match correspondente for avaliada como true.
Contexto do bloco
Um contexto de bloco é uma coleção de variáveis que estão disponíveis dentro desse bloco. Os sub-blocos podem acessar o contexto dos blocos pais. Blocos pais não podem acessar o contexto de sub-blocos.
Expressão
Uma expressão é um fragmento que usa a mesma sintaxe das expressões de linha única. Consulte Funções de atributos.

Tipos de instrução suportados

Há três tipos de instruções suportadas.
  • Contexto
  • Retornar
  • Se

Instrução de contexto

Uma instrução context é usada para inicializar e designar valores a variáveis nomeadas. Ela suporta dois operadores.
:=
Este operador é usado para inicializar uma nova variável dentro do bloco de contexto no qual a instrução é avaliada. Por exemplo, se uma variável for inicializada dentro de um if.block, ela não ficará disponível fora desse bloco nas instruções subsequentes.
=
Este operador é usado para atribuir um valor a uma variável existente. A variável pode existir no bloco de contexto atual ou em um bloco pai.
O formato é context: {{varname}} := {{expression}}. O uso é context.{{varname}} para acessar {{varname}} em instruções subsequentes no mesmo bloco ou sub-blocos.

Instrução Return

A instrução de retorno é usada para indicar ao mecanismo de regras que finalize a execução e retorne imediatamente o valor que foi calculado.

O formato é return: {{expression}}.

Instrução Se

A instrução if é usada para a construção de blocos condicionais. Ela é composta por várias propriedades, ao contrário das duas instruções anteriores.

Tabela 1.
Nome Descrição Formato
match Se essa condição for avaliada como true, o block correspondente será executado. match: 1 == 2
block Um bloco limitado de instruções que devem ser executadas se match for avaliada como true. Uma matriz YAML de instruções padrão
elsifs Matriz de condições else-if que são avaliadas caso match não seja avaliada como true. Matrizes YAML que são instruções if aninhadas
else Bloco de instruções que são executadas caso o resultado da avaliação não seja true para match e nem para qualquer tipo de elseifs.match. Uma matriz YAML de instruções

Criação de logs de rastreio

É possível adicionar o registro de rastreamento a uma regra de várias linhas para enviar registros de depuração. As propriedades de registro de rastreamento são aplicadas se uma regra for executada com o modo de rastreamento ativado. O registro de rastreamento é suportado pelas debug propriedades e debugx .

debug declaração

A debug instrução é usada para indicar a execução da expressão fornecida e registrar o valor retornado. A expressão deve sempre resultar em uma sequência de caracteres.

Formato - debug: {{expression}}

debugx bloqueio

O debugx bloco é composto por duas propriedades: log e fields.

Nome Descrição Formato
log A expressão fornecida é avaliada e o valor retornado é registrado. A expressão deve sempre resultar em uma sequência de caracteres. log: {{expression}}
Campos Campos de metadados personalizados que são enviados junto com o log. Fornecido na forma de um mapa de pares chave-valor. O valor de cada par é uma expressão que deve resultar em uma sequência de caracteres. {{field_key}}: {{expression}}

Consulte a seção para ver um exemplo de função que ilustra o registro de rastreamento.

Fragmentos

Esta lista de trechos não é completa e não abrange todos os usos possíveis de regras. No entanto, essa lista fornece algumas amostras que podem ser usadas no estado em que se encontram ou podem ser ampliadas.

Observação: Como a sintaxe de várias linhas segue o YAML formato, a indentação correta é fundamental para que a regra personalizada funcione corretamente.

Obter o nome de exibição do gerente

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")

Transformar o domínio de e-mail

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: ""

Definição de escopo de variáveis

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

O resultado é 7. Esse resultado é porque a linha 6 reinicializa ret dentro do if.block. As instruções aninhadas subsequentes veem essa variável. No entanto, depois que o mecanismo de regra sai do if.block, ele pode acessar a variável que foi inicializada na linha 2.

Exemplo de registro de rastreamento

Este exemplo ilustra como usar instruções de registro de rastreamento.

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

Para a debug instrução, a expressão fornecida será avaliada e registrada como "This is an example of a trace log at time <timestamp>".

Para o debugx bloco, a expressão fornecida será avaliada e registrada como "The user id obtained: <user id>". Os seguintes campos de metadados personalizados serão enviados junto com o log.
Chave Valor
"flow" "login"
"time" "<timestamp>"
"userEmail" "user@test.com"

Restrições importantes

  • As variáveis que são inicializadas pelo quadro context podem viver apenas dentro desse quadro ou de subquadros dentro dele. No exemplo de regra anterior, a variável managerName não fica acessível fora do quadro if no qual ela foi inicializada.
  • Os quadros elseifs e else poderão ser usados apenas se um quadro if estiver no mesmo nível.
  • Todos os quadros if e elseifs devem ter uma expressão match que sempre retorne um valor Booleano.
  • Se o fluxo de avaliação de regra não encontrar uma instrução return, um valor nulo será retornado. Nenhum erro é lançado nem a verificação de sintaxe é executada para certificar-se de que todos os fluxos possíveis tenham um return. O autor da regra deve assegurar que todos os fluxos da regra retornem um valor aceitável.