Search code examples
javadroolsexistsaccumulate

Using the equivalent of 'not exists' within drools accumulate


My question is about using the equivalent of the 'not exists' construct within a Drools accumulate function.

I make use of a simple accumulation of Performance objects with the following rule part which compiles fine and produces expected results:

rule "rule-conflicting-code-set-1" 
...
when
...
    $conflicts : List(size() > 1) 
            from accumulate( 
                $p : Performance(code == "FOO", /*other conditions*/)  
                from $patient.performances,
                collectList($p)) 

then
...
end

Now I would like to extend the rule with an extra condition. I want to prevent Performances that satisfy a certain condition from being accumulated (ie, ending up in the $conflicts list).

The new condition is: I do not want to accumulate a Performance for which there exists an Attention that contains that performance. Attention is an object with a performanceSet field that holds objects of type Performance (Set performanceSet;). I created thisPerformance() as a method of Performance as a way to refer to $p.

The condition itself would look like this:

not exists Attention(performanceSet contains thisPerformance())

I tried to rewrite the corresponding accumulate like this:

$conflicts : List(size() > 1) 
        from accumulate( 
            $p : Performance(
                       code == "FOO", 
                       not exists Attention(performanceSet contains 
                           thisPerformance()),
                       /*other conditions*/)  
            from $patient.performances,
            collectList($p)) 

The compiler complains about the 'exists' keyword: [ERR 102] Line 50:40 mismatched input 'exists' in rule "rule-conflicting-code-set-1". Parser returned a null Package.

I suspect that the solution to my problem will look quite different, but let the example serve as an explanation of what I would like to achieve.


Solution

  • not exists is not a valid construct in Drools. Simply use not instead.

    Then, what you are looking for is to use multiple patterns in the accumulate. You need to rewrite your rule to something like this:

    $conflicts : List(size() > 1) 
        from accumulate( 
            ($p : Performance(code == "FOO") from $patient.performances and
            not Attention(performanceSet contains $p)),
            collectList($p)) 
    

    Hope it helps,