-------
Drools 5.2 is almost done and we have something very cool added. As
previous blogs have mentioned, we recently added positoinal
syntax and prolog like derivation query based backward chaining.
However those queries were pull only and didn't support the recently
added live "open
queries". It also had the problem that it was method recursion
based, so could blow the method stack if it was too deep.
5.2 is now stack based and supports "open queries", you just miss of
the '?'. So what this means is you can have TMS over reactive
derivation queries. If I have a key in an envelop on a desk in an
office I can add a TMS justifcation that will only exist while the
key remains in the office.
This should have some very interesting use cases and I look forward
to seeing what people come up with. For instance you could create a
rule to monitor a project's maven dependencies and transititive
depdencies and receive an alert if ASL/MIT/BSD project has a GPL
dependency added via a transititive dependency.
It's a bit abstract, but here is the unit test showing it working:
package org.drools.test
import java.util.List
import java.util.ArrayList
import org.drools.Person
global List list
dialect "mvel"
declare Location
thing : String
location : String
end
query isContainedIn( String x, String y )
Location(x, y;)
or
( Location(z, y;) and isContainedIn(x, z;) )
end
rule look when
Person( $l : likes )
isContainedIn( $l, 'office'; )
then
insertLogical( 'blah' );end
rule existsBlah when
exists String( this == 'blah')
then
list.add( 'exists blah' );end
rule notBlah when
not String( this == 'blah')
then
list.add( 'not blah' );end
rule init when
then
insert( new Location("apple", "kitchen") );
insert( new Location("desk", "office") );
insert( new Location("flashlight", "desk") );
insert( new Location("envelope", "desk") );
insert( new Location("key", "envelope") );
insert( new Location("washing machine", "cellar") );
insert( new Location("nani", "washing machine") );
insert( new Location("broccoli", "kitchen") );
insert( new Location("crackers", "kitchen") );
insert( new Location("computer", "office") );
end
rule go1 when
String( this == 'go1')
then
list.add( rule.getName() );
insert( new Location('lamp', 'desk') );
end
rule go2 when
String( this == 'go2')
$l : Location('lamp', 'desk'; )
then
list.add( rule.getName() );
retract( $l );
end
rule go3 when
String( this == 'go3')
then
list.add( rule.getName() );
insert( new Location('lamp', 'desk') );
end
rule go4 when
String( this == 'go4')
$l : Location('lamp', 'desk'; )
then
list.add( rule.getName() );
modify( $l ) { thing = 'book' };
end
rule go5 when
String( this == 'go5')
$l : Location('book', 'desk'; )
then
list.add( rule.getName() );
modify( $l ) { thing = 'lamp' };
end
rule go6 when
String( this == 'go6')
$l : Location( 'lamp', 'desk'; )
then
list.add( rule.getName() );
modify( $l ) { thing = 'book' };
end
rule go7 when
String( this == 'go7')
$p : Person( likes == 'lamp' )
then
list.add( rule.getName() );
modify( $p ) { likes = 'key' };
end
-----
[go1, exists blah, go2, not blah, go3, exists blah, go4, not blah, go5, exists blah, go6, not blah, go7, exists blah]
-----
Person p = new Person();
p.setLikes( "lamp" );
FactHandle handle = ksession.insert( p );
ksession.fireAllRules();
list.clear();
FactHandle fh = ksession.insert( "go1" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go1", list.get(0));
assertEquals( "exists blah", list.get(1));
fh = ksession.insert( "go2" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go2", list.get(2));
assertEquals( "not blah", list.get(3));
fh = ksession.insert( "go3" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go3", list.get(4));
assertEquals( "exists blah", list.get(5));
fh = ksession.insert( "go4" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go4", list.get(6));
assertEquals( "not blah", list.get(7));
fh = ksession.insert( "go5" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go5", list.get(8));
assertEquals( "exists blah", list.get(9));
// This simulates a modify of the root DroolsQuery object, but first we break it
fh = ksession.insert( "go6" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go6", list.get(10));
assertEquals( "not blah", list.get(11));
// now fix it
fh = ksession.insert( "go7" );
ksession.fireAllRules();
ksession.retract( fh );
assertEquals( "go7", list.get(12));
assertEquals( "exists blah", list.get(13));
System.out.println( list );