多行规则执行器
通常需要构建多行规则以计算属性的期望值。 IBM® Verify 支持配置简单的单行规则和更复杂的多行规则。
有关单行语法规则,请参阅 “属性函数 ”。
多行规则的元素
以 YAML 格式撰写多行规则。 其受 YAML 文档的格式化需求所约束。 使用的 YAML 解析器支持大多数 YAML 1.1 和 1.2。
重要的是了解以下术语。
- 语句
- 语句是规则构建块且可以是不同类型。 例如,return 语句计算提供的表达式并将表达式返回为规则值。
- 阻止
- 块是语句的限定集合。 规则从名为
statements的顶级块开始。 块可以存在于特定语句类型中。 例如,if.block是要在对应的if.match语句求值为 true 时执行的语句的集合。 - 块上下文
- 块上下文是此块中提供的变量的集合。 子块可访问父块的上下文。 父块无法访问子块的上下文。
- 表达式
- 表达式是使用与单行表达式相同语法的片段。 参见 “属性函数 ”。
受支持的语句类型
支持三种类型的语句。
- 上下文
- 退货
- If
Context 语句
context 语句用于初始化并将值分配给指定的变量。 其支持两个操作。:=- 此运算符用于初始化评估语句的上下文块中的新变量。 例如,如果在
if.block中初始化变量,因此在此块的后续语句中不可用。
=- 此运算符用于将值分配给现有变量。 变量可存在于当前上下文块或父块中。
context: {{varname}} := {{expression}}。 使用 context.{{varname}} 以访问相同块或子块的后续语句中的 {{varname}}。Return 语句
Return 语句用于指示规则引擎结束执行并立即返回计算的值。
格式为 return: {{expression}}。
If 语句
if 语句用于构建条件块。 其包含多个属性,与先前两个语句不同。
| 名称 | 描述 | 格式 |
|---|---|---|
match |
如果此条件求值为 true,那么将执行对应的 block。 |
match: 1 == 2 |
block |
在 match 求值为 true 时必须执行的限定的语句块。 |
语句的标准 YAML 数组 |
elsifs |
在 match 未能求值为 true 时评估的 else-if 条件的数组。 |
作为嵌套 if 语句的 YAML 数组 |
else |
在 match 和所有 elseifs.match 未能求值为 true 时执行的语句块。 |
语句的 YAML 数组 |
跟踪日志记录
可以在多行规则中添加跟踪日志功能,以便发送调试日志。 如果规则在启用跟踪模式的情况下执行,则会执行跟踪日志属性。 通过 和 debugx 属性支持跟踪日志记录 debug 。
debug语句该
debug语句用于指示执行所提供的表达式,并记录返回的值。 该表达式应始终求值为字符串。格式 -
debug: {{expression}}
debugx阻止fields该debugx区块包含两个属性:log和。名称 描述 格式 日志 对给定的表达式进行求值,并将返回的值记录下来。 该表达式应始终求值为字符串。 log: {{expression}}字段 随日志一起发送的自定义元数据字段。 以键值对数组的形式提供。 每对数据的值都是一个表达式,其计算结果必须为字符串。 {{field_key}}: {{expression}}请参阅该章节 ,其中提供了一个演示跟踪日志记录的示例函数。
片段
此片段列表不详尽并且不涵盖所有可能的规则使用。 但是,此列表提供一些可使用或者可扩展的样本。
注意: 由于多行语法遵循 格式 YAML ,正确的缩进对于自定义规则的正常运行至关重要。
获取经理的显示名称
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")
转换电子邮件域
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: ""
变量的作用域限定
statements:
- context: ret := 3 + 4
- if:
match: 2 > 1block:
- context: ret := 5
- if:
match: 3 > 2block:
- context: ret = 0
- return: context.ret
结果是 7。 if.block出现这种结果是因为第6行在 内重新初始化 ret 了。 后续嵌套语句都会看到此变量。 但是,在规则引擎退出 if.block 后,它可以访问在第 2 行已初始化的变量。
跟踪日志示例
此示例演示了如何使用跟踪日志语句。
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
对于该 debug 语句,系统将对提供的表达式进行求值,并将其记录为 "This is an example of a trace log at time <timestamp>"。
对于该
debugx 块,提供的表达式将被求值并记录为 "The user id obtained: <user id>"。 以下自定义元数据字段将随日志一并发送。| 键 | 值 |
|---|---|
"flow" |
"login" |
"time" |
"<timestamp>" |
"userEmail" |
"user@test.com" |
重要限制
- 由
context框架初始化的变量只能存在于该框架内或其子框架内。 在先前规则示例中,变量managerName在其初始化所在的if框架之外不可访问。 - 仅当
if框架处于相同级别时,才能使用elseifs和else框架。 - 所有
if和elseifs框架必须具有一个始终返回布尔值的match表达式。 - 如果规则评估流程未遇到
return语句,那么返回空值。 没有抛出错误,也没有执行语法检查以确保所有可能的流程都具有return。 规则的作者必须确保规则的所有流程都返回一个可接受的值。