Check for specific element in a list in Drools

20,956

If the A instances are in the working memory as you say (ideal scenario), just write the rule using it:

rule X
when
    A( name == "bob", value == 10 )
...

Inserting collections (lists, trees, etc) into the working memory directly is not recommended, because they are abstract data structures without any intrinsic semantic attached. But lets say you have a Person class, that contains a list of Addresses, and you want to execute the rule for each address in Montreal, Canada, without inserting the addresses themselves as facs. You can write:

rule X
when
    Person( $addresses : addresses )
    Address( city == "Montreal", country == "CA" ) from $addresses
...

Finally, if you really want to use the list itself as a fact (again, bad practice), you can do the following, but note that it will match all lists in the working memory:

rule X
when
    $list : List()
    A( name == "bob", value == 10 ) from $list
...
Share:
20,956
serena
Author by

serena

Updated on February 25, 2020

Comments

  • serena
    serena over 4 years

    I just have started using Drools (version 5.1.0) so please bear with me in case this question was already answered.

    I have a java.util.List object which contains objects of complex type A, with A as:

    class A {
      String name; 
      String Value;}
    

    The list as well as its elements are in the working memory of the Drools engine. Is there an easy way to fire a rule only if the name and value of an element in the list are matching specific values?

    Currently, i am using a self-defined function inside the Drools rule, which iterates over the list and returns true if there is an element that matches the specification, however i wonder whether this is the most efficient and easiest use.

  • mike9322
    mike9322 over 12 years
    +1 for beating me to the punch with essentially the same answer I was in the middle of writing.
  • Kraken
    Kraken over 11 years
    @Edson Tirelli How do I break out of a loop. Say for each Address, I've got a function that returns me boolean; hence I do Person($addresses : addresses); $a : Address() from $addresses; eval($e.returnBoolean()); then //do something; Now if after getting the eval; if it is true; it do something and then I wan to get out of the loop. How do I go about that?
  • Ajeesh
    Ajeesh over 8 years
    @Edson Tirelli Do you know how do I define something like $list : List<Person>() in drools?
  • Edson Tirelli
    Edson Tirelli over 8 years
    You can't. Java erasure removes type information, so it is not possible to do it. It is a JVM limitation. More details here: docs.oracle.com/javase/tutorial/java/generics/erasure.html
  • Kadir Kalkan
    Kadir Kalkan over 6 years
    Hi @EdsonTirelli can u tell me how can i reach each item in a list as your example i define $list : List() but i want to send each value to a function. For example :function (return variable + "checked") when (select list send each value to function from list) then (write returned function value)
  • Edson Tirelli
    Edson Tirelli over 6 years
    just bind the element to a variable. In the example above, just write: $a : A(...) from $list. Then $a will be bound to each element of the list and you can invoke your function passing $a as a parameter.