DROOLS模式匹配具有复杂对象的嵌套列表

时间:2014-12-06 00:18:34

标签: drools

我正在努力使用DROOL中的模式匹配例程来遍历复杂嵌套对象的列表。

我有一个像这样的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

我知道它可以用这样的方式编写,其中每个元素迭代匹配但我只想触发一次动作并且如果有任何匹配则有一个A列表。 谢谢!

2 个答案:

答案 0 :(得分:5)

这不可能使用&#34;收集&#34;因为在收集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

答案 1 :(得分:0)

使用collectSet()而不是collectList()来修复语法和删除A的重复项的一些细微更改

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将DROOLs noob指向正确的方向!

此外,值得注意的是,使用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