2014-12-06 202 views
2

我在遍歷複雜嵌套對象列表的DROOL中使用模式匹配例程。DROOLS模式匹配複雜對象的嵌套列表

我有一個POJO結構是這樣的:

class MyFact { 
    private List<A> listOfA; 
    public List<A> getListOfA() { return listOfA; } 
} 

class A { 
    private List<B> listOfB; 
    private String stringField; 
    public List<B> getListOfB() { return listOfB; } 
    public String getStringField() { return stringField; } 
} 

class B { 
    private String otherStringField; 
    public String getOtherStringField() { return otherStringField; } 
} 

我試圖找到正確的語法來蒐集相匹配的一套標準,其中還包括在對象匹配字段類型「A」的所有對象包含在'A的listOfB中。

我認爲規則需要是這個樣子,但我有格局將無法編譯,而它裏面的collect(...)

import java.util.ArrayList; 
rule "Tricky Syntax" 
when 
    $myFact: MyFact() 
    $filteredListOfA: ArrayList(size > 0) from collect ( 
     A(stringField == "something", $listOfB: listOfB) from $myFact.listOfA 
     B(otherStringField == "somethingElse") from $listOfB 
    ) 
then 
    // Do something neat with $filteredListOfA 
end 

我知道它會以這樣的方式被寫入其中的每個元素是迭代匹配的,但我只想發起一次行動,並有一個單一的列表,如果有任何匹配。 謝謝!

回答

4

這是不可能usind「收集」,因爲收集CE內部不可能有多種模式。 (你的意思是收集A或B的或兩者兼而有之?)你可以很容易地改變這種積累,讓你在什麼積累完全控制:

$myFact: MyFact() 
$filteredListOfA: List(size > 0) from accumulate ( 
    $a: A(stringField == "something", $listOfB: listOfB) from $myFact.listOfA 
    and 
    B(otherStringField == "somethingElse") from $listOfB; 
    collectList($a) 
) 

後來

如果列表中的元素應該只發生一旦listOfA中的元素被多次選中,只需使用SetcollectSet即可。

+0

這是非常有用的,讓我更進一步,但不是100%正確。 需要刪除;在「somethingElse」之後並將ArrayList導入更改爲List(以避免類轉換異常 - 將UnmodifyableRandomAccessList更改爲ArrayList)。 修正後,如果我們在$ listOfB中有多個匹配的對象B,代碼將返回一個filteredListOfA,其中包含A的重複項。 現在我明白了積累CE更好,我想我可以解決這個問題。謝謝。 – Joe 2014-12-08 14:52:20

+0

感謝您的反饋。我添加Set作爲消除重複的替代品 – laune 2014-12-08 15:14:22

+0

@laune請看看這個http://stackoverflow.com/questions/35067399/drools-6-1-0-defaultfacthandle-notserializable-exception – Kumar 2016-02-02 10:22:59

0

一些輕微的變化以固定語法並去除A,使用collectSet(的一式兩份)

代替collectList()

import java.util.Set; 
rule "Tricky Syntax" 
when 
    $myFact: MyFact() 
    $filteredListOfA: Set(size > 0) from accumulate ( 
     $a: A(stringField == "something", $listOfB: listOfB) from $myFact.listOfA 
     and 
     B(otherStringField == "somethingElse") from $listOfB; 
     collectSet($a) 
    ) 
then 
    // Do something with the $filteredListOfA Set 
end 
由於 laune爲在正確的方向指向一個流口水小白!

此外,值得注意的是,使用collectSet()和collectList()匹配順序不一定會保留(由於DROOLs LIFO行爲)。這是一個替代解決方案,保留動作的匹配順序(如果這很重要)。

import java.util.Set; 
import java.util.LinkedHashSet; 
rule "Tricky Syntax" 
when 
    $myFact: MyFact() 
    $filteredListOfA: Set(size > 0) from accumulate ( 
     $a: A(stringField == "something", $listOfB: listOfB) from $myFact.listOfA 
     and 
     B(otherStringField == "somethingElse") from $listOfB, 
     init(Set set = new LinkedHashSet();), 
     action(set.add($a);), 
     result(set) 
    ) 
then 
    // Do something with the $filteredListOfA Set 
end