我无法在DROOLS 6.2和Optaplanner中使用两个Java类为嵌套成员/对象分配局部变量。我试图确定两个事实/实例嵌套成员何时具有相同的值。下面的测试用例很简单,实际上我试图在规则中比较多个嵌套成员。
public class A {
private B x;
//public B getX(), public void setX(B b) follow ...
}
public class B {
private int y;
//public int getY(), public void setY(int y) follow ...
}
rule "testnestedmembers"
when
A(x.y : y, $x : x)
A(x2.y == y, $x : x2)
then
scoreHolder.addHardConstraintMatch(kcontext,-1000);
Message [id=1, level=ERROR, path=org/somebody/project/planner/solver/planScoreRules.drl, line=16, column=0
text=[ERR 102] Line 16:49 mismatched input ':' in rule "testnestedmembers"]
Message [id=2, level=ERROR, path=org/somebody/project/planner/solver/planScoreRules.drl, line=0, column=0 text=Parser returned a null Package]
---
Warning Messages:
---
Info Messages:
at org.optaplanner.core.config.score.director.ScoreDirectorFactoryConfig.buildKieBase(ScoreDirectorFactoryConfig.java:387)
我已经回顾了一些答案,例如: Drools Rule Expression : Access Nested class data member
Geoffrey De Smet的回答说明了有条件的,但不是本地的任务。 我尝试了不同的变化,但没有运气。谢谢你的任何建议。
编辑我应该说创建一个绑定而不是分配一个本地变量。
答案 0 :(得分:0)
你的意思不是这样的:
when
$a1 : A($y1 : x.y)
A(this != $a1, x.y == $y1)
then
...
正如Geoffrey De Smet所说:
在DRL中,
之类的操作==
表示等于,而不是相同。使用$varB : b
,您可以执行B varB = a.getB();
答案 1 :(得分:0)
首先,我将指出导致编译器错误的原因。
rule "testnestedmembers"
when
A(x.y : y, $x : x) // (1)
A(x2.y == y, $x : x2) // (2) (3)
(1)绑定的格式为<variable> : <field>
,但x.y
不是有效的变量名。
(2)与x2.y
相同。此外,x2
不是A中的字段。
(3)没有什么能阻止规则引擎将相同的事实与A类的两种模式相匹配。这意味着该规则将触发A类的每一个事实,因为(因为你的意图)Axy总是等于它自己。 / p>
正确
rule "testnestedmembers"
when
$a1: A( $x1: x )
A( this != $a1, $x2: x, $x1.getY() == $x2.getY() )
then
...
然而!此规则触发两次,一次绑定到$ a1的一个事实,一次绑定到$ a1的另一个(匹配)。一种可能性是测试这样一对(或群集)的存在:
rule "testnestedmembers"
when
$a1: A( $x1: x )
exists A( this != $a1, $x2: x, $x1.getY() == $x2.getY() )
then
...
另一种选择是通过测试属性来确保排序:
rule "testnestedmembers"
when
$a1: A( $x1: x, $id: id )
exists A( id > $id, $x2: x, $x1.getY() == $x2.getY() )
then
现在这会激发每一对A,其中第二对有更大的(唯一!)id。