Drools - 当部分抛出错误时,在dslr中对多个dsl条件进行分组

时间:2016-10-06 14:06:04

标签: drools dsl rules rule-engine

创建一个小规则引擎并使用drools。我的设计就像开发人员(我是:))将开发dsl,业务用户可以创建规则(dslr)。

dsl档案

[When]When [Pp]urchase amount is greater than "{Value}" = e : Event(EventAction.isPurchaseGreaterThan(e,{Value}))
[When]If [Cc]ustomer tier equals to "{CustomerTier}"=e1 : Event(EventAction.isCustomerTierEqualTo(e1,"{CustomerTier}")
[Then]Give "{Discount}" Percentage Discount = RewardAction.applyDiscount(e, {Discount});
[Then]Suggest Redemption = System.out.println("Redemption Suggested");

dslr档案

rule "Discount For Purchase-1"
    when (When purchase amount is greater than "100") && (If customer tier equals to "Silver")
    then     #Error is thrown in this line
        Give "5" Percentage Discount 
end 

其余的java代码与示例中给出的类似。在此代码中出现以下错误

错误

Line 15:4 mismatched input 'then' in rule "Discount For Purchase-1"

以下dslr工作正常

rule "Discount For Purchase-1"
    when (When purchase amount is greater than "100")
    then
        Give "5" Percentage Discount 
end 

生成DRL

when (e : Event(EventAction.isPurchaseGreaterThan(e,100))) && (e : Event(EventAction.isCustomerTierEqualTo(e,"Silver"))

关于此生成的DRL的说明 - 我可能会因为' e而得到重复的变量错误。这是另一个问题。但是,为了解决这个问题,我甚至尝试将第二个变量修改为“e1'在dsl。

为了您的信息,我已尝试以下方法解决错误,但注意到帮助了我

When (When purchase amount is greater than "100" && If customer tier equals to "Silver")
When (When purchase amount is greater than "100" and If customer tier equals to "Silver")
When ((When purchase amount is greater than "100") && (If customer tier equals to "Silver"))
When ((When purchase amount is greater than "100") and (If customer tier equals to "Silver"))
When ((When purchase amount is greater than "100") and (If customer tier equals to "Silver"));
When ((When purchase amount is greater than "100") && (If customer tier equals to "Silver"));

更新:

生成drl

=== DRL xpanded from DSLR ===
   1  #created on: 5 Oct, 2016
   2  package com.test.loyalty.rules
   3  
   4  #list any import classes here.
   5  import com.test.loyalty.*
   6  import com.test.loyalty.model.*
   7  import com.test.loyalty.util.*
   8  
   9  
  10  
  11  #declare any global variables here
  12  
  13  rule "Discount For Purchase-1"
  14      when 
  15        e : Event(EventAction.isPurchaseGreaterThan(e,100))
  16        e1 : Event(EventAction.isCustomerTierEqualTo(e1,"Silver")
  17      then
  18          System.out.println("Redemption Suggested"); 
  19  end
  20  
  21  rule "Discount For Purchase-2"
  22      when
  23          e : Event(EventAction.isPurchaseGreaterThan(e,100))
  24        e1 : Event(EventAction.isCustomerTierEqualTo(e1,"Gold")
  25      then
  26          System.out.println("Redemption Suggested"); 
  27  end
  28  


=============================
[ERR 102] Line 17:4 mismatched input 'then' in rule "Discount For Purchase-1"
17
[ERR 102] Line 25:4 mismatched input 'then' in rule "Discount For Purchase-2"
25
java.lang.IllegalArgumentException: Could not parse knowledge.
    at com.test.loyalty.LoyaltyTest.readKnowledgeBase(LoyaltyTest.java:124)
    at com.test.loyalty.LoyaltyTest.init(LoyaltyTest.java:104)
    at com.test.loyalty.LoyaltyTest.main(LoyaltyTest.java:38)

有人可以帮我这个吗?提前谢谢。

2 个答案:

答案 0 :(得分:0)

您将要在顶层组合两种模式(使用类EventAction),因此不需要运算符,并且&&无论如何组合模式都是错误的 - 它可用于模式中的约束。

rule "Discount For Purchase-1"
when
    When purchase amount is greater than "100"
    If customer tier equals to "Silver"
then    
    Give "5" Percentage Discount 
end 

我想知道你是否确实考虑过两个Event-s的组合。如果不是,那么在一种模式中组合约束会更好 - 尽管这有点棘手。 (参见文档。)或者,您可以通过在附加约束中使用类似this == e的内容来强制绑定到第二个模式(同一类)的另一个事实的标识。

修改 现在您已经添加了扩展文本,它突出显示:Event(EventAction.isCustomerTierEqualTo(e1," Silver")在最后错过了一个右括号,在另一个规则中错过了相同的东西。修复了替换规则DSL。

您可以在任意数量的规则中使用相同的变量,但不能将同一规则中的两个模式绑定到同一个变量。您可能需要稍微重新设计DSL,例如

# creates the Person pattern and binds $person
[condition][]There is a Person with=$person:Person()

# write a comparison using a field reference and a value
[condition][]- his {field} {operator} {value}=
             {field} {operator} {value}

DSLR变为:

when
    There is a Person with
    - his call_count is less than 10 or name is equal to "Joe" 
    - his points is greater than 5
then

扩展为

when
    $person:Person(call_count  <  10 || name == "Joe", points  >  5)
then

当然,您需要运营商(或您的职能)的定义

[condition][]is greater than=>
[condition][]is equal to===

最初的连字符是必不可少的,你需要在第一个参数({field})前面提供一些东西(&#34;他的&#34;或者#34;)。

答案 1 :(得分:0)

我认为报价出现问题&#34;&#34;在您的值100.尝试重写为

When]When [Pp]urchase amount is greater than {Value} = = e : Event(EventAction.isPurchaseGreaterThan(e,"{Value}"));

在编写规则时,无需插入引号。当然,如果您的Value是String,那么这是真的。如果是int,则排除引号。另一个建议,为了看到你的规则转换,你应该插入

/# debug: display result

在dsl文件的开头和结尾。