Проблема с аксессорами в Drools
Я столкнулся с определенным сценарием при обновлении составных объектов в Drools:
declare A
@propertyReactive
flag: Boolean
end
declare B
flag: Boolean
end
declare C
@propertyReactive
attrA: A
attrB: B
end
rule "Create A"
when
not A()
then
insert(new A());
System.out.println("OBJECT A CREATED");
end
rule "Create B"
when
not B()
then
insert(new B());
System.out.println("OBJECT B CREATED");
end
rule "Create C"
when
$A:A()
$B:B()
not C()
then
insert(new C($A,$B));
System.out.println("OBJECT C CREATED");
end
rule "Modify A"
when
$A:A(flag == false)
C()
then
modify($A) {setFlag(true)};
String $output = "Now A is " + $A.getFlag();
System.out.println($output);
end
rule "Print C when C is False"
when
C($A:attrA, attrA.flag == false, $B:attrB)
then
String $output = "A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
rule "Print C when C is True"
when
C($A:attrA, attrA.flag == true, $B:attrB)
then
String $output = "A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
rule "Print C when C is True 2"
when
C($A:attrA, $B:attrB)
A(this == $A, flag == true)
then
String $output = "2 A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
Выход:
OBJECT A CREATED
OBJECT B CREATED
OBJECT C CREATED
A is false and B is false
Now A is true
2 A is true and B is false
Итак, у меня есть следующие вопросы:
- Почему правило "Печать C, когда C - Истина" не срабатывает?
- Почему мне нужно переписать это правило как "Print C, когда C - True 2", чтобы оно работало?
- У кого-нибудь есть объяснение этому?
Похоже, что у Drools есть проблема при работе со средствами доступа вложенных классов...
Большое спасибо.
1 ответ
Drools реагирует только на изменения, выполненные для объектов, используемых в ваших шаблонах, а не на любые ссылки на вложенные объекты, которые они могут содержать. И это не совсем верно.
Когда вы изменяете факт в Drools (или любой из его вложенных ссылок на объекты), у вас есть возможность сообщить Drools об этой модификации или нет. В вашем случае вы никогда не будете уведомлять Drools о них. Вот почему ваши правила зависят от (не детерминированного) порядка оценки.
Если вы хотите, чтобы Drools "знал" об изменениях факта, вы должны использовать modify
или же update
функции в RHS правил, где эти модификации происходят.
В вашем конкретном случае у вас есть не только вложенные объекты, но и вложенные факты: A
а также C
, Даже если A
это факт, изменения на A
(даже если должным образом уведомлено Drools) никогда не будет вызывать переоценку шаблона следующим образом:
C(attrA.flag == true)
Причина в том, что тип шаблона C
и не A
, В таких сценариях правило, написанное как ваше Print C when C is True 2
Правило это лучший подход.
Надеюсь, поможет,