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