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. :)