Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters in drools

How can I pass a parameter to set the comparing value of age(18 should be dynamic) in the below drools rule

package com.rule.models

import com.rule.models.User

rule "AgeCheck"
when
    $user: User( age < 18 )
then
    System.out.println("Warning, "+$user.getName()+" is below age!");
end
like image 852
ir2pid Avatar asked May 01 '14 15:05

ir2pid


People also ask

How do you call a function in drools?

Here is an example of calling java method from drools. setLocalTax() method is available from ItemCity class. Using the '$item' object we can invoke.

How do you fire specific rules in drools?

To associcate a Customer with rules you need: class Customer { private String name; private List<String> rules; //... } So you are saying to create agenda for each customer and fire the rules based on agenda...

How do you make a decision table in drools?

A Drool Decision Table is a way to generate rules from the data entered into a spreadsheet. The spreadsheet can be a standard Excel (XLS) or a CSV File. In this spreadsheet a simple rule is included: if the Customer object's age parameter equals to “1” the Customer is allowed a discount of 15%.


2 Answers

For rules in Drools, there is nothing comparable to "parameter passing". Data used in rules must come from facts in Working Memory or from global variables.

Using the first technique would look like this:

rule "AgeCheck"
when
    Parameter( $ageLimit: ageLimit )
    $user: User( age < $ageLimit )
then ... end

A single fact of class Parameter must be inserted initially; it may contain more than one parameter.

Using a global variable is also possible:

global my.app.Parameter parameter

rule "AgeCheck"
when
    $user: User( age < parameter.getAgeLimit() )
then ... end

See the Expert manual for details about how to install a global.

like image 86
laune Avatar answered Sep 21 '22 18:09

laune


For a bit of fun I thought I'd knock up a little example DRL demonstrating how this might be done by inserting AgeLimit facts.

declare AgeLimit
    country: String
    age: int
end
declare Bar
    country: String
    revellers: java.util.Collection
end
declare Person
    age: int
end
declare ThrowOutOfTheBar
    person: Person
    bar: Bar
end

rule "UK drinking age" salience 1000 when then
    insertLogical( new AgeLimit( 'uk', 18 ) );
end
rule "US drinking age" salience 1000 when then
    insertLogical( new AgeLimit( 'us', 21 ) );
end

rule "Can I buy a beer?" when
    $p: Person()
    $bar: Bar( revellers contains $p )
    AgeLimit( country == $bar.country, age > $p.age )
then
    insertLogical( new ThrowOutOfTheBar($p, $bar) );
end

To reduce the amount of hand-cranked DRL further, you could insert those AgeLimit facts using the API. For example, you could maintain a database table of national age limits and at the start of your session you could insert them all into working memory as facts. Alternatively, you could create a decision table which generates those same age limit insertions rules behind the scenes. This is likely to be a good way to manage things if for example, you wish to maintain an age limit for every country.

Furthering these ends of keeping hard-coded values out of key rules, it would be worth reading up on inference and truth maintenance. This could lead to a rule such as:

rule "Can I buy a beer?" when
    $p: Person()
    $bar: Bar( revellers contains $p )
    IsUnderAge( person == $p, country == $bar.country )
then
    insertLogical( new ThrowOutOfTheBar($p, $bar) );
end

This has the benefit of encapsulating the rules around age limits and providing some re-use potential. However to achieve it in the example above involves inserting IsUnderAge facts for every person for every country in which they are under age. Working out whether that would be a good thing was leading me into all sorts of off-topic thinking, so I left it out. :)

like image 23
Steve Avatar answered Sep 20 '22 18:09

Steve