I am inserting let's say about 1000 pojos of type A in to the kiesession how can I add a rule in drools to do some task if duplicate pojos exists for A in the kiesession.
class A {
private int someInt;
private String someString;
}
function boolean checkDuplicate(List input) {
int a = input.size();
int b = ((List) input.stream().distinct().collect(Collectors.toList())).size();
return a!=b;
}
dialect "java"
rule "ADuplicateRule"
when
$input : List( ) from collect(A())
eval(checkDuplicate($input))
then
throw new Exception("A list has duplicate values");
end
The above approach is working but is there a better more simpler way to achieve this?
like to do validation on sum of a field of pojo in the kiesession we can just simply write this
$sumSomeInt: Integer(this > 90) from accumulate(A( $SomeInt: someInt ), sum($SomeInt))
is it possible to do something on the similar lines to check for duplicates?
You were pretty close:
rule "Duplicates Found"
when
A( $i: someInt, $s: someString )
List( size > 1 ) from collect( A( someInt == $i, someString == $s ) )
then
// handle the duplicate case
end
Adjust your equality check as needed. I would recommend not throwing an exception out of the 'then'.
Alternatively, you don't even need to collect a full list of duplicates; it's sufficient that there exists at least one duplicate. This makes your rule more like this:
rule "Duplicates found - v2"
when
$a: A( $i: someInt, $s: someString )
exists( A( this != $a, someInt == $i, someString == $s ))
then
// handle the duplicates case
end
In these rules we're taking advantage of the fact that Drools will implicitly check all instances of A
in working memory. So in the first rule, for each A
, it will check to see if there are duplicates of that instance; if there are, the rule triggers. Otherwise it checks the next instance of A
, and so on, until all instances of A
have been evaluated.
The second rule relies on the same sort of workflow, but also includes a this != $a
check on the exists
clause to verify that the "duplicate" we found isn't actually the instance we're checking. Since the first rule only triggers for List( size > 1 )
, it expects that the instance we're checking will be included in the result of the collect
.