Definitions public class Applicant { private String name; private int age; private boolean valid; // getter and setter methods here } rule "Is of valid age" when $a : Applicant( age < 18 ) then modify ( $a ) { valid = false }; ends
Definitions public class Room { private String name // getter and setter methods here } public class Sprinkler { private Room room ; private boolean on ; // getter and setter methods here } public class Fire { private Room room ; // getter and setter methods here } public class Alarm { }
Definitions rule "When there is a fire turn on the sprinkler" when Fire ($room : room) $sprinkler : Sprinkler ( room == $room, on == false ) then modify ( $sprinkler ) { on = true }; println ( "Turn on the sprinkler for room " + $room.name ); end rule "When the fire is gone turn off the sprinkler" when $room : Room ( ) $sprinkler : Sprinkler ( room == $room, on == true ) not Fire ( room == $room ) then modify ( $sprinkler ) { on = false }; println ( "Turn off the sprinkler for room " + $room.name ); end
Definitions rule "Raise the alarm when we have one or more fires" when exists Fire () then insert ( new Alarm () ); println ( "Raise the alarm" ); end rule "Cancel the alarm when all the fires have gone" when not Fire () $alarm : Alarm () then retract ( $alarm ); println ( "Cancel the alarm" ); end
Definitions rule "Status output when things are ok" when not Alarm () not Sprinkler ( on === true ) then println ( "Everything is ok" ); end
Executing String [] names = new String []{ "kitchen" , "bedroom" , "office" , "livingroom" }; Map < String , Room > name2room = new HashMap < String , Room >(); for ( String name : names ){ Room room = new Room ( name ); name2room .put( name , room ); ksession .insert( room ); Sprinkler sprinkler = new Sprinkler ( room ); ksession .insert( sprinkler ); } ksession .fireAllRules() > Everything is ok
Executing Fire kitchenFire = new Fire ( name2room.get( "kitchen" ) ); Fire officeFire = new Fire ( name2room.get( "office" ) ); FactHandle kitchenFireHandle = ksession .insert( kitchenFire ); FactHandle officeFireHandle = ksession .insert( officeFire ); ksession .fireAllRules(); > Raise the alarm > Turn on the sprinkler for room kitchen > Turn on the sprinkler for room office
Executing ksession .retract( kitchenFireHandle ); ksession .retract( officeFireHandle ); ksession .fireAllRules() > Turn off the sprinkler for room office > Turn off the sprinkler for room kitchen > Cancel the alarm > Everything is ok rule "Status output when things are ok" when not Alarm () not Sprinkler ( on === true ) then println ( "Everything is ok" ); end
not Bus( color = “red” ) Conditional Elements exists Bus( color = “red” ) forall ( $bus : Bus( floors == 2 ) Bus( this == $bus, color == “red” ) ) forall ( $bus : Bus( color == “red” ) )
Accumulate CE rule "accumulate" when $sum : Number( intValue > 100 ) from accumulate ( Bus( color == "red" , $t : takings ) sum( $t ) ) then print "sum is “ + $sum; end
Accumulate CE Patterns and CE's can be chained with ' from ' rule "collect" when $zipCode : ZipCode() $sum : Number( intValue > 100 ) from accumulate ( Bus( color == "red" , $t : takings ) from $hbn.getNamedQuery( “Find Buses” ) .setParameters( [ “zipCode” : $zipCode ] ) .list(), sum( $t ) ) then print "sum is “ + $sum; end
Timers rule “name” timer 1m30s when $l : Light( status == “on” ) then modify ( $l ) { status = “off” }; rule “name” timer (int: 1m30s 0) when $l : Light( status == “on” ) then modify ( $l ) { status = “off” }; When the light is on, and has been on for 1m30s then turn it off Same as above. Interval timer with JDK semantics for initial duration, then repeat duration.
Timers rule “name” timer ( cron: 0 0/15 * * * * ) when Alarm( ) then sendEmail( ”Alert Alert Alert!!!” ) Field Name Mandatory? Allowed Values Allowed Special Characters Seconds YES 0-59 , - * / Minutes YES 0-59 , - * / Hours YES 0-23 , - * / Day of month YES 1-31 , - * ? / L W Month YES 1-12 or JAN-DEC , - * / Day of week YES 1-7 or SUN-SAT , - * ? / L # Year NO empty, 1970-2099 , - * / Send alert every quarter of an hour
Calendars rule "weekdays are high priority" calendars "weekday" timer (int:0 1h) when Alarm() then send( "priority high - we have an alarm” ); end rule "weekend are low priority" calendars "weekend" timer (int:0 4h) when Alarm() then send( "priority low - we have an alarm” ); end Execute now and after 1 hour duration Execute now and after 4 hour duration
TMS and Inference rule "Issue Child Bus Pass" when $p : Person ( age < 16 ) then insert(new ChildBusPass ( $p ) ); end rule "Issue Adult Bus Pass" when $p : Person ( age >= 16 ) then insert(new AdultBusPass ( $p ) ); end Couples the logic What happens when the Child stops being 16?
When the rule is no longer true, the object is retracted. when $p : Person ( age < 16 ) then logicalInsert ( new IsChild ( $p ) ) end when $p : Person ( age >= 16 ) then logicalInsert ( new IsAdult ( $p ) ) end de-couples the logic Maintains the truth by automatically retracting
TMS and Inference rule "Issue Child Bus Pass" when $p : Person ( ) IsChild ( person =$p ) then logicalInsert ( new ChildBusPass ( $p ) ); end rule "Issue Adult Bus Pass" when $p : Person ( age >= 16 ) IsAdult ( person =$p ) then logicalInsert ( new AdultBusPass ( $p ) ); end The truth maintenance cascades
TMS and Inference rule "Issue Child Bus Pass" when $p : Person ( ) not ( ChildBusPass ( person == $p ) ) then requestChildBusPass( $p ); end The truth maintenance cascades
$c : Custumer( type == “VIP ) $oe : BuyOrderEvent( customer == $c ) from entry-point “Home Broker Stream” not BuyAckEvent( relatedEvent == $oe.id, this after[1s, 10s] $oe ) from entry-point “Stock Trader Stream” Operators Existing Drools 'not' Conditional Elements can be used to detect non-occurrence of events BackAckEvent must occur between 1s and 10s ' after' BuyOrderEvent
Aggregations Rule Engines do not deal with aggregations $n : Number( intValue > 100 ) from accumulate ( $s : StockTicker( symbol == “RHAT” ) over window:time ( 5s ), average ( $s.price ) ) Over 5 seconds Aggregate ticker price for RHAT over last 5 seconds The pattern 'Number' reasons 'from' the accumulate result
CEP Applied at FedEx Custom Critical * Presented by Adam Mollemkopf at ORF 2009
CEP Applied at FedEx Custom Critical * Presented by Adam Mollemkopf at ORF 2009
HAL : Without your space helmet, Dave, you're going to find that rather difficult.
Dave Bowman : HAL, I won't argue with you anymore! Open the doors!
HAL : Dave, this conversation can serve no purpose anymore. Goodbye. Joshua: Greetings, Professor Falken. Stephen Falken : Hello, Joshua. Joshua: A strange game. The only winning move is not to play. How about a nice game of chess?