我是Drools的新手。想问一个有关条件元素的问题。我有一些类,下面的UML图显示了这些对象之间的关系: UML diagram
一个订单有一个客户,并有一个订单行列表。 每个订单行都链接到一个项目。坦率地说,这是一本关于Drools的书的示例代码。
当订单的客户为SILVER类别并且订单中的所有商品都在高范围(高成本)时,我想触发以下规则,以便设置订单的折扣。这是规则:
rule "Silver Customers + High Range Order - 10% Discount -1"
when
$o: Order( $lines : orderLines.size >= 2, $customer: customer, discount == null )
$c: Customer( category == Category.SILVER, this == $customer )
forall( OrderLine( this memberOf $lines, $item : item)
Item(this == $item, category == Item.Category.HIGH_RANGE)
)
then
$o.setDiscount(new Discount(10.0));
update($o);
end
问题是规则总是触发,即使我尝试在低范围内插入一个包含5个项目的订单。
在调试信息中,我发现第一个项目的类别是LOW_RANGE,但规则仍然被触发:
==>[BeforeActivationFiredEvent: getActivation()=[[ Silver Customers + High Range Order - 10% Discount active=false ] [ null
[fact 0:1:1561745898:141057847:1:DEFAULT:NON_TRAIT:org.drools.devguide.eshop.model.Customer:Customer [id = null, age=null, email=null, name=null, category = SILVER]]
[fact 0:12:1971991758:-345298280:12:DEFAULT:NON_TRAIT:org.drools.devguide.eshop.model.Order:Order [ id = null, customer=Customer [id = null, age=null, email=null, name=null, category = SILVER], date=Fri Oct 21 11:11:38 CST 2016, lines=[OrderLine [item=Item{id=1, name=A, cost=80.0, salePrice=800.0, category=LOW_RANGE}, quantity=1], OrderLine [item=Item{id=1, name=B, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=2], OrderLine [item=Item{id=1, name=C, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=3], OrderLine [item=Item{id=1, name=D, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=4], OrderLine [item=Item{id=1, name=E, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=5]], state=PENDING, discount=null]] ] ], getKnowledgeRuntime()=KieSession[0]]
-------------------
rule triggered:Silver Customers + High Range Order - 10% Discount
==>[AfterActivationFiredEvent: getActivation()=[[ Silver Customers + High Range Order - 10% Discount active=false ] [ null
[fact 0:1:1561745898:141057847:1:DEFAULT:NON_TRAIT:org.drools.devguide.eshop.model.Customer:Customer [id = null, age=null, email=null, name=null, category = SILVER]]
[fact 0:12:1971991758:-345298280:18:DEFAULT:NON_TRAIT:org.drools.devguide.eshop.model.Order:Order [ id = null, customer=Customer [id = null, age=null, email=null, name=null, category = SILVER], date=Fri Oct 21 11:11:38 CST 2016, lines=[OrderLine [item=Item{id=1, name=A, cost=80.0, salePrice=800.0, category=LOW_RANGE}, quantity=1], OrderLine [item=Item{id=1, name=B, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=2], OrderLine [item=Item{id=1, name=C, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=3], OrderLine [item=Item{id=1, name=D, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=4], OrderLine [item=Item{id=1, name=E, cost=800.0, salePrice=850.0, category=HIGH_RANGE}, quantity=5]], state=PENDING, discount=10.0 % ]] ] ], getKnowledgeRuntime()=KieSession[0]]
我已阅读问题的答案:forall always evaluates to be true [Drools]。我尝试了解决方案,但是我得到了另一个错误的结果,即使我使用了包含所有高范围项目的订单,下面的规则也不会触发:
rule "Silver Customers + High Range Order - 10% Discount"
when
$o: Order( $lines : orderLines.size >= 2, discount == null )
$c: Customer( category == Category.SILVER ) from $o.customer
forall( OrderLine() from $o.orderLines
OrderLine( item.category == Item.Category.HIGH_RANGE)
)
then
$o.setDiscount(new Discount(10.0));
update($o);
end
单位测试代码如下:
@Test
public void highRangeOrderDiscountTest() {
KieSession kSession = createDefaultSession();
Order o = ModelFactory.getOrderWithFiveHighRangeItems();
kSession.insert(o.getCustomer());
kSession.insert(o.getOrderLines().get(0));
kSession.insert(o.getOrderLines().get(1));
kSession.insert(o.getOrderLines().get(2));
kSession.insert(o.getOrderLines().get(3));
kSession.insert(o.getOrderLines().get(4));
kSession.insert(o.getOrderLines().get(0).getItem());
kSession.insert(o.getOrderLines().get(1).getItem());
kSession.insert(o.getOrderLines().get(2).getItem());
kSession.insert(o.getOrderLines().get(3).getItem());
kSession.insert(o.getOrderLines().get(4).getItem());
kSession.insert(o);
int fired = kSession.fireAllRules();
// We have 5 Items that are categorized -> 5 rules were fired
// We have 1 Customer that needs to be categorized -> 1 rule fired
// We have just one order with all HIGH RAnge items -> 1 rule fired
// One Coupon is created for the SILVER Customer -> 1 rule fired
assertThat(8, is(fired));
assertThat(o.getCustomer().getCategory(), is(Customer.Category.SILVER));
assertThat(o.getDiscount(), not(nullValue()));
assertThat(o.getDiscount().getPercentage(), is(10.0));
}
}
你能告诉我原因还是告诉我forall的正确使用方法?非常感谢。
答案 0 :(得分:0)
这确定了OrderLine-s的集合,然后确定所有属于高范围项目。 (注意:未经测试)
rule "Silver Customers + High Range Order - 10% Discount"
when
$c: Customer( category == Category.SILVER )
$o: Order( $lines : orderLines.size >= 2, customer == $c,
discount == null )
forall( OrderLine( $item : item) from $lines
Item(this == $item, category == Item.Category.HIGH_RANGE))
then
modify( $o ){ setDiscount(new Discount(10.0)) }
end
必须将所有Customer和Item对象作为事实插入;为OrderLine-s做这个也是合理的。
答案 1 :(得分:0)
这本书有一个错误:
$ o:Order($ lines:orderLines.size> = 2,客户== $ c,折扣== null)
必须为
$ o:Order($ lines:orderLines,orderLines.size> = 2,客户== $ c,折扣== null)