Reputation: 53
I am having trouble assigning a local variable with nested members/objects in DROOLS 6.2 and Optaplanner with two Java classes. I am trying to determine when two facts/instances nested members have the same values. The test case below is simple, in reality I'm trying to compare multiple nested members in a rule.
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)
I have reviewed some answers, such as: Drools Rule Expression : Access Nested class data member
And Geoffrey De Smet's answer illustrates a conditional, but not a local assignment. I've tried different variations, but no luck. Thank you for any advice.
Edit: I should have said creating a binding instead of assigning a local variable.
Upvotes: 0
Views: 2240
Reputation: 31300
First I'll point out what causes the compiler errors.
rule "testnestedmembers"
when
A(x.y : y, $x : x) // (1)
A(x2.y == y, $x : x2) // (2) (3)
(1) A binding has the form <variable> : <field>
, but x.y
isn't a valid variable name.
(2) Same with x2.y
. Also, x2
isn't a field in A.
(3) Nothing keeps the rule engine from matching the same fact with both patterns for class A. This means that the rule will fire for each and every fact of class A, since (as you intend) A.x.y is always equal to itself.
Correct is
rule "testnestedmembers"
when
$a1: A( $x1: x )
A( this != $a1, $x2: x, $x1.getY() == $x2.getY() )
then
...
However! This rule fires twice, once with one fact bound to $a1, and once with the other (matching) one bound to $a1. One possibility is to test for the existence of such a pair (or cluster!):
rule "testnestedmembers"
when
$a1: A( $x1: x )
exists A( this != $a1, $x2: x, $x1.getY() == $x2.getY() )
then
...
Another option is to ensure an ordering by testing an attribute:
rule "testnestedmembers"
when
$a1: A( $x1: x, $id: id )
exists A( id > $id, $x2: x, $x1.getY() == $x2.getY() )
then
Now this fires for each pair of A's where the second has a greater (unique!) id.
Upvotes: 0
Reputation: 15230
Don't you mean something like this :
when
$a1 : A($y1 : x.y)
A(this != $a1, x.y == $y1)
then
...
As Geoffrey De Smet said :
In DRL,
==
means equals, not same. With$varB : b
you do something likeB varB = a.getB();
Upvotes: 1