drools dsl 将表达式添加到带有“-”的最后一个模式不起作用
drools dsl adding expression to last pattern with '-' not working
我使用 drools 规则有一段时间了,最近才开始使用 dsl 以使最终用户更容易编写规则。虽然我已经能够定义一个简单的 dsl 并按预期正确编译成 drl,但我无法使 'adding constraints to previous expression' 的 dsl 功能正常工作。
我什至尝试了 drools dsl 指南中最简单的示例,这不会将我定义的以“-”开头的条件编译到前面的表达式中。我在编译它时不断收到规则 "Rule1Sample_0" 中的“输入不匹配 'price'”错误。
正如我所说,我有这个用于简单的条件表达式和结果表达式。但是按照文档添加约束根本不起作用。
我正在使用 drools 7.0 版。0.Final,这是不是直到更高版本才支持的东西?
在我测试的简单示例中,我的 dsl 文件仅包含:
[condition][]There is a {ShoppingCart} that=${ShoppingCart!lc} : ${ShoppingCart!ucfirst}()
[condition][]- total price is greater than 1000 =totalPrice > 1000
[consequence]Update {ShoppingCart}=System.out.println("{ShoppingCart}" + " test")
这是条件
"There is a ShoppingCart that total price is greater than 1000"
我为我的模板的 when 和 then 部分指定的操作:
"Action" "Update ShoppingCart"
这是我将其传递给 DrlParser 之前编译的 drl:
rule "Test1"
dialect "mvel"
when
"There is a ShoppingCart that total price is greater than 1000"
then
"Update ShoppingCart"
end
上面的代码片段运行后,expandedDrl 字符串包含以下内容:
package com.sample.test
rule "Test1"
dialect "mvel"
when
$shoppingcart : $Shoppingcart() total price is greater than 1000
then
System.out.println("ShoppingCart" + " test")
end
这是我使用 DRLParser 解析时为此生成的 drl:
(代码片段在此,部分省略)
DrlParser parser = new DrlParser();
DefaultExpanderResolver resolver = new DefaultExpanderResolver(new StringReader(dsl));
String expandedDrl = parser.getExpandedDRL(dslr, resolver);
上面的代码片段运行后,expandedDrl 字符串包含以下内容:
package com.sample.test
rule "Test1"
dialect "mvel"
when
$shoppingcart : $Shoppingcart() total price is greater than 1000
then
System.out.println("ShoppingCart" + " test")
end
以及我在控制台中看到的编译器错误:
[[13,43]: [ERR 102] Line 13:43 mismatched input 'price' in rule "Test1" ....
你能试试条件吗
There is a ShoppingCart that
- total price is greater than 1000
你能试试下面的dsl吗
... business definitions
[when]complex condition = (simple condition
or another condition)
[when]simple condition = (total price is not 0)
[when]another condition = (total price greater than 10)
... field definitions
[when]total price = totalPrice
... consequences I advise to wrap in java util class each as a static method to write java code in java code
[consequence]Update {ShoppingCart}=System.out.println("{ShoppingCart}" + " test")
... tech dsl at the bottom
[when]There (is( an?)?|are) {entityType}s?( that)? = ${entityType}: {entityType}()
[when](is\s+)?not less than(\s+an?)? = >=
[when](is\s+)?less than(\s+an?)? = <
[when](is\s+)?not greater than(\s+an?)? = <=
[when](is\s+)?greater than(\s+an?)? = >
[when]((is|do(es)?)\s+)?not equals?(\s+to)? = !=
[when](is\s+)?equals?(\s+to)? = ==
[when]is not(\s+an?)? = !=
[when]is(\s+an?)? = ==
[when]like(\s+an?)? = matches
[when]{prefix}?\s*(?<![\w])and(?![\w])\s*{suffix}? = {prefix} && {suffix}
[when]{prefix}?\s*(?<![\w])or(?![\w])\s*{suffix}? = {prefix} || {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*\({suffix}? = {prefix} false == (true && {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*{suffix}? = {prefix} !{suffix}
[when](?<![^\(,])\s*- =
这应该能够处理像
这样的规则
There is a ShoppingCart that
- total price is greater than 1000
- not complex condition
如果您想在其他条件中重用条件,您希望它们是原子的。用大括号 () 拥抱 RHS 的好经验法则,不要破坏记录的原子性
测试
@DroolsSession({ "classpath:/test.rdslr", "classpath:/business.dsl", "classpath:/keywords.dsl" })
public class PlaygroundTest {
@Rule
public DroolsAssert drools = new DroolsAssert();
@Test
public void testIt() {
drools.insertAndFire(new ShoppingCart(BigDecimal.valueOf(1000.5)));
drools.insertAndFire(new ShoppingCart(BigDecimal.valueOf(999)));
}
}
域
public class ShoppingCart {
public BigDecimal totalPrice;
public ShoppingCart(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
}
rdslr
rule Test1
when
There is a ShoppingCart that
- total price is greater than 1000
then
print eligible price
end
rule Test2
when
There is a ShoppingCart that
- worth a discount
then
print eligible price
end
business.dsl
[when]worth a discount =
(total price is not less than 500
and not over limit
or total price is greater than 5000)
// stupid condition just for demonstration
[when]over limit = ((total price + total price * 0.05) > total price + 50)
[when]total price = totalPrice
[then]print eligible price = System.out.println($ShoppingCart.totalPrice);
keywords.dsl
[when]There (is( an?)?|are) {entityType}s?( that)? = ${entityType}: {entityType}()
[when](is )?not within\s*\({tail}?= not in ({tail}
[when](is )?within\s*\({tail}?= in ({tail}
[when](is )?not one of\s*\({tail}?= not in ({tail}
[when](is )?one of\s*\({tail}?= in ({tail}
[when]ignore case '{tail}?= '(?i){tail}
[when]{param:[$\w\.!'\[\]]+} as {param2:[$\w\.!'\[\]]+}=(({param2}) {param})
[when](is\s+)?not less than(\s+an?)? = >=
[when](is\s+)?less than(\s+an?)? = <
[when](is\s+)?not greater than(\s+an?)? = <=
[when](is\s+)?greater than(\s+an?)? = >
[when]((is|do(es)?)\s+)?not equals?(\s+to)? = !=
[when](is\s+)?equals?(\s+to)? = ==
[when]is not(\s+an?)? = !=
[when]is(\s+an?)? = ==
[when]like(\s+an?)? = matches
[when]{prefix}?\s*(?<![\w])and(?![\w])\s*{suffix}? = {prefix} && {suffix}
[when]{prefix}?\s*(?<![\w])or(?![\w])\s*{suffix}? = {prefix} || {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*\({suffix}? = {prefix} false == (true && {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*{suffix}? = {prefix} !{suffix}
[when](?<![^\(,])\s*- =
测试输出
00:00:00 --> inserted: ShoppingCart[totalPrice=1000.5]
00:00:00 --> fireAllRules
00:00:00 <-- 'Test1' has been activated by the tuple [ShoppingCart]
1000.5
00:00:00 --> inserted: ShoppingCart[totalPrice=999]
00:00:00 --> fireAllRules
00:00:00 <-- 'Test2' has been activated by the tuple [ShoppingCart]
999
我使用 drools 规则有一段时间了,最近才开始使用 dsl 以使最终用户更容易编写规则。虽然我已经能够定义一个简单的 dsl 并按预期正确编译成 drl,但我无法使 'adding constraints to previous expression' 的 dsl 功能正常工作。 我什至尝试了 drools dsl 指南中最简单的示例,这不会将我定义的以“-”开头的条件编译到前面的表达式中。我在编译它时不断收到规则 "Rule1Sample_0" 中的“输入不匹配 'price'”错误。 正如我所说,我有这个用于简单的条件表达式和结果表达式。但是按照文档添加约束根本不起作用。 我正在使用 drools 7.0 版。0.Final,这是不是直到更高版本才支持的东西?
在我测试的简单示例中,我的 dsl 文件仅包含:
[condition][]There is a {ShoppingCart} that=${ShoppingCart!lc} : ${ShoppingCart!ucfirst}()
[condition][]- total price is greater than 1000 =totalPrice > 1000
[consequence]Update {ShoppingCart}=System.out.println("{ShoppingCart}" + " test")
这是条件
"There is a ShoppingCart that total price is greater than 1000"
我为我的模板的 when 和 then 部分指定的操作:
"Action" "Update ShoppingCart"
这是我将其传递给 DrlParser 之前编译的 drl:
rule "Test1"
dialect "mvel"
when
"There is a ShoppingCart that total price is greater than 1000"
then
"Update ShoppingCart"
end
上面的代码片段运行后,expandedDrl 字符串包含以下内容:
package com.sample.test
rule "Test1"
dialect "mvel"
when
$shoppingcart : $Shoppingcart() total price is greater than 1000
then
System.out.println("ShoppingCart" + " test")
end
这是我使用 DRLParser 解析时为此生成的 drl:
(代码片段在此,部分省略)
DrlParser parser = new DrlParser();
DefaultExpanderResolver resolver = new DefaultExpanderResolver(new StringReader(dsl));
String expandedDrl = parser.getExpandedDRL(dslr, resolver);
上面的代码片段运行后,expandedDrl 字符串包含以下内容:
package com.sample.test
rule "Test1"
dialect "mvel"
when
$shoppingcart : $Shoppingcart() total price is greater than 1000
then
System.out.println("ShoppingCart" + " test")
end
以及我在控制台中看到的编译器错误:
[[13,43]: [ERR 102] Line 13:43 mismatched input 'price' in rule "Test1" ....
你能试试条件吗
There is a ShoppingCart that
- total price is greater than 1000
你能试试下面的dsl吗
... business definitions
[when]complex condition = (simple condition
or another condition)
[when]simple condition = (total price is not 0)
[when]another condition = (total price greater than 10)
... field definitions
[when]total price = totalPrice
... consequences I advise to wrap in java util class each as a static method to write java code in java code
[consequence]Update {ShoppingCart}=System.out.println("{ShoppingCart}" + " test")
... tech dsl at the bottom
[when]There (is( an?)?|are) {entityType}s?( that)? = ${entityType}: {entityType}()
[when](is\s+)?not less than(\s+an?)? = >=
[when](is\s+)?less than(\s+an?)? = <
[when](is\s+)?not greater than(\s+an?)? = <=
[when](is\s+)?greater than(\s+an?)? = >
[when]((is|do(es)?)\s+)?not equals?(\s+to)? = !=
[when](is\s+)?equals?(\s+to)? = ==
[when]is not(\s+an?)? = !=
[when]is(\s+an?)? = ==
[when]like(\s+an?)? = matches
[when]{prefix}?\s*(?<![\w])and(?![\w])\s*{suffix}? = {prefix} && {suffix}
[when]{prefix}?\s*(?<![\w])or(?![\w])\s*{suffix}? = {prefix} || {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*\({suffix}? = {prefix} false == (true && {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*{suffix}? = {prefix} !{suffix}
[when](?<![^\(,])\s*- =
这应该能够处理像
这样的规则There is a ShoppingCart that
- total price is greater than 1000
- not complex condition
如果您想在其他条件中重用条件,您希望它们是原子的。用大括号 () 拥抱 RHS 的好经验法则,不要破坏记录的原子性
测试
@DroolsSession({ "classpath:/test.rdslr", "classpath:/business.dsl", "classpath:/keywords.dsl" })
public class PlaygroundTest {
@Rule
public DroolsAssert drools = new DroolsAssert();
@Test
public void testIt() {
drools.insertAndFire(new ShoppingCart(BigDecimal.valueOf(1000.5)));
drools.insertAndFire(new ShoppingCart(BigDecimal.valueOf(999)));
}
}
域
public class ShoppingCart {
public BigDecimal totalPrice;
public ShoppingCart(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
}
rdslr
rule Test1
when
There is a ShoppingCart that
- total price is greater than 1000
then
print eligible price
end
rule Test2
when
There is a ShoppingCart that
- worth a discount
then
print eligible price
end
business.dsl
[when]worth a discount =
(total price is not less than 500
and not over limit
or total price is greater than 5000)
// stupid condition just for demonstration
[when]over limit = ((total price + total price * 0.05) > total price + 50)
[when]total price = totalPrice
[then]print eligible price = System.out.println($ShoppingCart.totalPrice);
keywords.dsl
[when]There (is( an?)?|are) {entityType}s?( that)? = ${entityType}: {entityType}()
[when](is )?not within\s*\({tail}?= not in ({tail}
[when](is )?within\s*\({tail}?= in ({tail}
[when](is )?not one of\s*\({tail}?= not in ({tail}
[when](is )?one of\s*\({tail}?= in ({tail}
[when]ignore case '{tail}?= '(?i){tail}
[when]{param:[$\w\.!'\[\]]+} as {param2:[$\w\.!'\[\]]+}=(({param2}) {param})
[when](is\s+)?not less than(\s+an?)? = >=
[when](is\s+)?less than(\s+an?)? = <
[when](is\s+)?not greater than(\s+an?)? = <=
[when](is\s+)?greater than(\s+an?)? = >
[when]((is|do(es)?)\s+)?not equals?(\s+to)? = !=
[when](is\s+)?equals?(\s+to)? = ==
[when]is not(\s+an?)? = !=
[when]is(\s+an?)? = ==
[when]like(\s+an?)? = matches
[when]{prefix}?\s*(?<![\w])and(?![\w])\s*{suffix}? = {prefix} && {suffix}
[when]{prefix}?\s*(?<![\w])or(?![\w])\s*{suffix}? = {prefix} || {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*\({suffix}? = {prefix} false == (true && {suffix}
[when]{prefix}?\s*(?<![\w])not(?! (in|matches|contains|memberOf|soundslike|str))(\s+an?)?(?![\w])\s*{suffix}? = {prefix} !{suffix}
[when](?<![^\(,])\s*- =
测试输出
00:00:00 --> inserted: ShoppingCart[totalPrice=1000.5]
00:00:00 --> fireAllRules
00:00:00 <-- 'Test1' has been activated by the tuple [ShoppingCart]
1000.5
00:00:00 --> inserted: ShoppingCart[totalPrice=999]
00:00:00 --> fireAllRules
00:00:00 <-- 'Test2' has been activated by the tuple [ShoppingCart]
999