1

I have been trying to figure this out on and off for a really long time. I can imagine a lot of very verbose and non-droolsy ways to go about accomplishing this. However, I would like to know the best practice for dealing with a situation like this. I would like to know how to write the constraint I describe below in the drools dialect.

I wish to write a constraint that deals with a collection. Let's say we have CustomType which has a field Collection. The constraint should express we want to find facts of CustomType who have any object in the collection other than the specified object(P). Critically, it does not matter if the specified object is present. It only matters if there is at least one other object in the collection.

The collection in question is not a set. It is possible there are multiple instances of P in the same collection.

In pseudo Java I might write a method like:

public Boolean isThereANotP(CustomType cs){
for(str : cs.Collection){
    if(str != P){
        return true}
}
return false
}

How would this be expressed in the when clause of a drool? The closest I could come is specifying there is not a P, but that isn't what I want. I want to know that there is a not P.

melchoir55
  • 6,842
  • 7
  • 60
  • 106

2 Answers2

1

Perhaps this?

$c: CustomType()
$notP: Object(this != objectP) from $c.collection

Actually that would activate for each object in the collection which is not objectP. This might be better:

$c: CustomType()
exists Object(this != objectP) from $c.collection
Steve
  • 9,270
  • 5
  • 47
  • 61
  • This worked well. It didn't occur to me to self-reference objects in the collection. Thanks! – melchoir55 Nov 22 '13 at 18:30
  • I have added a related question here: http://stackoverflow.com/questions/20157162/drools-constraint-object-does-not-exist-whose-member-field-contains-a-value-othe If you have a convenient moment to review it as well then I would appreciate it. – melchoir55 Nov 23 '13 at 00:57
0

Careful, the pseudo code you have posted will return true if the first element of your collection is not a P. Or, to be more generic, it returns true if you have any no P before a P or not P at all. Assuming that what you are looking for is:

find facts of CustomType who have any object in the collection other than the specified object(P)

you could write a rule similar to this:

global P objectP; //I'm using a global, but you could use a fact, or a binding in one of your fact's fields. 

rule "Find CustomType with no P"
when
    $c: CustomType(collection not contains objectP)
then
    //use $c
end

I don't know how to interpret the rest of your requirement though:

Critically, it does not matter if the specified object is present. It only matters if there is at least one other object in the collection.

If your requirement is that collections should not be empty, then you could write your pattern as:

CustomType(collection.empty == false , collection not contains objectP)

Hope it helps,

Esteban Aliverti
  • 6,259
  • 2
  • 19
  • 31
  • As I read it, the requirement is to activate for collections which contain at least one object which is not objectP, whereas your rule only activates for collections which do not contain objectP. – Steve Nov 22 '13 at 08:59
  • @Steve, if that was the requirement, then you answer is correct. – Esteban Aliverti Nov 22 '13 at 11:48
  • Maybe @melchoir55 will confirm which is the correct interpretation? :) – Steve Nov 22 '13 at 12:03
  • Thank you for the response, Esteban. Steve is accurate in his interpretation of my objective. The code you present will identify facts who do not contain object P. I wish to identify facts who contain objects which are themselves not P, but it is irrelevant whether a P is in the collection. – melchoir55 Nov 22 '13 at 17:45