Проблема с аксессорами в 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 Правило это лучший подход.

Надеюсь, поможет,

Другие вопросы по тегам