http://blog.athico.com/2011/06/truth-maintenance-over-directed-graphs.html

-------

Truth Maintenance over Directed Graphs using Reactive Derivation Queries

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 );