Search code examples
javadroolsrulesrule-engine

Java - Generic Drools rule


I would like to create my rule more Generic format which mean it should be validate the fields and values. Following my POJO structure.

 public class RulesModel
private String field;
private List<String> values;
// other stuff  

And my rule

rule "sample"
when
    $rule : RulesModel( field == "source", values contains "facebook", values contains "youtube", value not contains "instagram" )  
then
    // actions
end  

It's working fine to validate single field, but i want to validate the multiple fields of RulesModel. So i desire to create the POJO

public class RulesModelList {

    private List<RulesModel> ruleList;
    // Getter & Setter
}

So now when i pass the list of RulesModel by using RulesModelList class the rule should be validate like below

$rule : RulesModel( field == "source", values contains "facebook") && $rule : RulesModel( field == "createdBy", values contains "admin")

How to validate that in Drools?

Thanks in advance.


Solution

  • If all you want to do is verify that those two (or three or however many) RulesModels are in the list, it's quite simple:

    // Example from question
    rule "Verify Facebook source and admin createdBy"
    when
      RulesModelList( $list: ruleList)
      exists(RulesModel( field == "source", values contains "facebook") from $list)
      exists(RulesModel( field == "createdBy", values contains "admin") from $list)
    then
      // do something
    end
    

    Basically I get the list of RulesModel out of the RulesModelList input and assign to $list. Then I verify that there exists a RulesModel instance that matches my 'source' criteria, and then one that matches the 'createdBy' criteria.

    In the example I used exists() instead of assigning a variable because my sample rule doesn't need to make use of the RulesModel instance on the right hand side. If you do need to do something with the RulesModel instance, simply replace exists() with an assignment like this:

    $source: RulesModel( field == "source", values contains "facebook") from $list
    $createdBy: RulesModel( field == "createdBy", values contains "admin") from $list
    

    There is no need to do an accumulate unless you're trying to iterate over the list and find things that match a certain criteria. For example, let's say that one of the "field" values is "updatedBy", and there can be multiple RulesModel instances with that field name. To get the subset of the RulesModel instances with field name "updatedBy", you'd use accumulate, as Mykhaylo demonstrated in his answer.

    But if all you want to do is verify that a list contains an object that meets your criteria, accumulate is overkill and this here is the appropriate solution.