2016-11-17 3 views
1

Как связать переменные с различными типами фактов, согласованными в группе or в правиле LHS?Связывание переменных с разными типами данных в случае «или» в правиле LHS

Например, если у меня есть следующее правило-файл:

package com.sample 

rule "Rule1" 
    when 
     object1: ObjectType1(id == 1) or 
     object2: ObjectType2(id == 2) 
    then 
     System.out.println(object1.getId()); 
     System.out.println(object2.getId()); 
end 

и я использую этот код драйвера:

package com.sample; 

import org.kie.api.runtime.KieSession; 

public class DroolsTest { 

    public static final void main(String[] args) { 
    try { 
     String ruleFilePath = "src/main/resources/rules/ruleFile.drl"; 
     KieSession kSession = KSessionUtil.buildKSession(ruleFilePath); 

     ObjectType1 o1 = new ObjectType1(1); 
     ObjectType2 o2 = new ObjectType2(2); 

     kSession.insert(o1); 
     kSession.insert(o2); 

     kSession.fireAllRules(); 

     System.out.println("Bye"); 
    } catch (Throwable t) { 
     t.printStackTrace(); 
    } 
    } 
} 

ObjectType1.java:

package com.sample; 

public class ObjectType1 { 
    public ObjectType1(int i) { 
    super(); 
    this.id = i; 
    } 

    public int getId() { 
    return id; 
    } 

    public void setId(int id) { 
    this.id = id; 
    } 

    public int id; 
} 

ObjectType2.java:

package com.sample; 

public class ObjectType12 { 
    public ObjectType2(int i) { 
    super(); 
    this.id = i; 
    } 

    public int getId() { 
    return id; 
    } 

    public void setId(int id) { 
    this.id = id; 
    } 

    public int id; 
} 

я получаю ошибку синтаксиса из плагина Drools Eclipse:

object1 cannot be resolved. 
object2 cannot be resolved. 

Если изменить or в правиле LHS для and, ошибка уходит.

Я использую Drools 6.2.0.

ответ

2

Трудная часть заключается в том, как Drools имеет дело с or операндами между узорами. В вашем примере, Drools будет разлагаться ваше правило на 2 независимых правила:

rule "Rule1_A" 
when 
    object1: ObjectType1(id == 1) 
then 
    System.out.println(object1.getId()); 
    System.out.println(object2.getId()); 
end 


rule "Rule1_B" 
when 
    object2: ObjectType2(id == 2) 
then 
    System.out.println(object1.getId()); 
    System.out.println(object2.getId()); 
end 

Как вы можете видеть, ошибка теперь становится все более очевидным.

Побочным эффектом, связанным с тем, что Drools имеет дело с or, также является отсутствие короткого замыкания в этой операции: если оба объекта присутствуют в вашей сессии, правило будет выполняться дважды.

Надеется, что это помогает,

+0

Так, значит, что нет никакого способа, чтобы проверить, какие факты вызвали правило ? Кроме того, в примечании, касающемся утверждения ', если оба объекта присутствуют в вашем сеансе, правило будет выполняться дважды.', Есть ли способ предотвратить это? –

+0

К сожалению, самый простой способ предотвратить это - создать 2 явных правила: '(A и! B)' и '(! A и B)'. –

+0

И если вы хотите быть пуристом, если у вас есть 'или' между вашими шаблонами, это должно означать, что логика, которую вы хотите выполнить, не зависит от того, какое условие было истинным;) –

1

Как уже упоминался в this answer by Esteban, не представляется возможное связать переменные таким образом.

Вместо того, что мы можем сделать, это создать класс-оболочку, которая будет содержать объект каждого из различных различных типов данных, необходимых для быть согласованы:

public class ObjectType { 
    ObjectType1 ob1; 
    ObjectType2 ob2; 

    // setters and getters 
} 

Теперь, если мы хотим, чтобы вставить объект, скажем, , ObjectType1 в сессии знаний:

ObjectType1 object1 = new ObjectType1(); 
kSession.insert(object1); 

мы могли бы вместо того, чтобы установить ObjectType.ob1 ссылаться object1, а затем вставить новый объект ObjectType в сессии:

ObjectType1 object1 = new ObjectType1(); 
ObjectType object = new ObjectType(); 
object.setOb1(object1); 
kSession.insert(object); 

Теперь в файле правил, мы должны были бы соответствовать объект типа ObjectType1 с ObjectType(getOb1() != null), а не ObjectType1():

rule "Rule1" 
    when 
     object: (ObjectType(ob1 != null && ob1.getId() == 1) or 
        ObjectType(ob2 != null && ob2.getId() == 2)) 
    then 
     if (object.getOb1() != null) 
     { 
      System.out.println(object.getOb1().getId()); 
     } 
     else 
     { 
      System.out.println(object.getOb2().getId()); 
     } 
end