Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DROOLS pattern matching nested lists with complex objects

Tags:

drools

I'm struggling with a pattern-matching routine in DROOLs that traverses lists of complex nested objects.

I have a POJO structure something like this:

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; }
}

I am trying to find the correct syntax to collect all objects of type 'A' that match a set of criteria that also includes matching fields in objects contained within 'A's listOfB.

I think the rule needs to look something like this, but the pattern I have won't compile while it is inside the 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

I know it could be written in such a way where each element is matched iteratively but I only want to fire the action once and have a single List of A if there are any matches. Thanks!

like image 948
Joe Avatar asked Jan 09 '23 07:01

Joe


1 Answers

This isn't possible usind "collect" because multiple patterns aren't possible inside the collect CE. (Do you mean to collect A's or B's or both?) You can easily change this to accumulate which gives you full control over what is accumulated:

$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 )
) 

Later

If list elements should occur only once when elements in listOfA are selected more than once, simply use a Set and collectSet.

like image 82
laune Avatar answered Mar 29 '23 23:03

laune