[jboss-svn-commits] JBL Code SVN: r5996 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests drools-core/src/main/java/org/drools/leaps drools-core/src/main/java/org/drools/leaps/util drools-core/src/test/java/org/drools/examples/manners drools-core/src/test/java/org/drools/leaps

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Aug 28 20:49:02 EDT 2006


Author: bagerman
Date: 2006-08-28 20:48:55 -0400 (Mon, 28 Aug 2006)
New Revision: 5996

Modified:
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/LeapsTest.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsFactHandle.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/LeapsMannersTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
Log:
1 another query unit test is fixed by adding fireAll()
2 modifyObject is reworked and many related changes are done including streamlined assert / retract and lazier not and exits evaluation.

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/LeapsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/LeapsTest.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/LeapsTest.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -34,7 +34,6 @@
 import org.drools.compiler.PackageBuilder;
 import org.drools.lang.DrlDumper;
 import org.drools.lang.descr.PackageDescr;
-import org.drools.leaps.LeapsRuleBase;
 import org.drools.rule.Package;
 import org.drools.rule.Rule;
 import org.drools.xml.XmlDumper;
@@ -75,6 +74,40 @@
                       results.size() );
     }
 
+
+    public void testTwoQuerries() throws Exception {
+        // @see JBRULES-410 More than one Query definition causes an incorrect Rete network to be built.
+        
+        final PackageBuilder builder = new PackageBuilder();
+        builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_TwoQuerries.drl" ) ) );
+        final Package pkg = builder.getPackage();
+
+        final RuleBase ruleBase = getRuleBase();
+        ruleBase.addPackage( pkg );
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+
+        final Cheese stilton = new Cheese( "stinky",
+                                     5 );
+        workingMemory.assertObject( stilton );
+        final Person per1 = new Person( "stinker", "smelly feet", 70);
+        final Person per2 = new Person( "skunky", "smelly armpits", 40);
+        
+        workingMemory.assertObject( per1 );
+        workingMemory.assertObject( per2 );
+
+        workingMemory.fireAllRules( );
+        
+        QueryResults results = workingMemory.getQueryResults( "find stinky cheeses" );
+        assertEquals( 1,
+                      results.size() );
+        
+        results = workingMemory.getQueryResults( "find pensioners" );
+        assertEquals( 1,
+                      results.size() );        
+    }    
+    
+
+    
     /**
      * leaps does not create activations upfront hence its inability to apply
      * auto-focus predicate in the same way as reteoo does. activations in
@@ -385,12 +418,4 @@
         assertEquals( "3 1", 
                       list.get( 1 ) );
     }
-    
-    public void testLogicalAssertionsWithExists() throws Exception {
-        // FIXME
-    }
-    
-    public void testTwoQuerries() throws Exception {
-        // FIXME
-    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -31,9 +31,18 @@
     final LeapsTuple tuple;
 
     final int        index;
+    
+    final int type;
 
-    FactHandleTupleAssembly(final LeapsTuple tuple,
+    public final static int EXISTS = 1;
+    
+    public final static int NOT = 2;
+    
+    
+    FactHandleTupleAssembly(final int type,
+                            final LeapsTuple tuple,
                             final int index) {
+        this.type = type;
         this.tuple = tuple;
         this.index = index;
     }
@@ -45,4 +54,8 @@
     protected LeapsTuple getTuple() {
         return this.tuple;
     }
+
+    public int getType() {
+        return type;
+    }
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -21,7 +21,6 @@
 
 import org.drools.common.DefaultFactHandle;
 import org.drools.common.PropagationContextImpl;
-import org.drools.leaps.util.IteratorFromPositionToTableStart;
 import org.drools.leaps.util.Table;
 import org.drools.leaps.util.TableIterator;
 import org.drools.spi.PropagationContext;
@@ -196,7 +195,6 @@
     protected void removeTuple( final LeapsTuple tuple ) {
         this.tuples.remove( tuple );
     }
-
     
     private final IdentityMap notAndExistsHashedTables;
 
@@ -205,15 +203,16 @@
     public void add( Object object ) {
         super.add( object );
         for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
+            // this will also add link to hash into the leapsfacthandle
             ((HashedTableComponent)it.next( )).add( (LeapsFactHandle)object );
         }
     }
 
     public void remove( Object object ) {
         super.remove( object );
-        for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
-            ((HashedTableComponent)it.next( )).remove( (LeapsFactHandle)object );
-        }
+        // during modify we need to directly remove facts from participating 
+        // hashes because modify can throw us off
+        ((LeapsFactHandle)object ).removeFromHash();
     }
 
     protected void createHashedSubTable(ColumnConstraints constraint) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -34,19 +34,13 @@
     }
 
     public void add( LeapsFactHandle factHandle ) {
-        Table table = this.getTable( factHandle, true );
+        Table table = this.getTable( factHandle);
         if (table != null) {
             table.add( factHandle );
+            factHandle.addHash(table);
         }
     }
 
-    public void remove( LeapsFactHandle factHandle ) {
-        Table table = this.getTable( factHandle, false );
-        if (table != null) {
-            table.remove( factHandle );
-        }
-    }
-
     public TableIterator reverseOrderIterator( Tuple tuple ) {
         Table table = this.getTable( tuple );
         if (table != null) {
@@ -115,13 +109,12 @@
         return ret;
     }
 
-    private Table getTable( LeapsFactHandle factHandle, boolean createIfNotThere ) {
+    private Table getTable( LeapsFactHandle factHandle ) {
         Table ret = null;
         Map currentMap = this.buckets;
         if (this.constraints.isAllowedAlpha( factHandle, null, null )) {
             if (this.numberOfVariableConstraints > 0) {
-                for (int i = 0; ( i < this.numberOfVariableConstraints )
-                        && ( currentMap != null ); i++) {
+                for (int i = 0; i < this.numberOfVariableConstraints; i++) {
                     Integer hash = DEFAULT_HASH;
                     if (this.constraints.getBetaContraints( )[i] instanceof VariableConstraint
                             && ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getEvaluator( )
@@ -136,7 +129,7 @@
                     if (i != ( this.numberOfVariableConstraints - 1 )) {
                         // we can not have null as a value to the key
                         Map map = (Map) currentMap.get( hash );
-                        if (map == null && createIfNotThere) {
+                        if (map == null) {
                             map = new HashMap( );
                             currentMap.put( hash, map );
                         }
@@ -144,7 +137,7 @@
                     }
                     else {
                         Table table = (Table) currentMap.get( hash );
-                        if (table == null && createIfNotThere) {
+                        if (table == null) {
                             table = new Table( this.comparator );
                             currentMap.put( hash, table );
                         }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -49,29 +49,21 @@
                                                   activation.getTuple( ) );
         }
         else {
-            if (activation.getRule( ).getActivationGroup( ) == null
-                    || ( activation.getRule( ).getActivationGroup( ) != null && this.getActivationGroup( activation.getRule( )
-                                                                                                                   .getActivationGroup( ) )
-                                                                                    .isEmpty( ) )) {
-                // fire regular rule
-                super.fireActivation( activation );
-                ((LeapsTuple)activation.getTuple( )).setWasFired( true );
-                if (activation.getRule( ).getActivationGroup( ) != null) {
-                    this.getActivationGroup( activation.getRule( ).getActivationGroup( ) );
-                }
-            }
+            // fire regular rule
+            super.fireActivation( activation );
+            ( (LeapsTuple) activation.getTuple( ) ).setWasFired( true );
         }
     }
-    
+
     /**
-     * to accomodate the difference between rete and leaps in storing 
-     * activations. we pull activations from rule to activations map
-     * we store in working memory to facilitate activations removal 
-     * when rule is removed from the memory
+     * to accomodate the difference between rete and leaps in storing
+     * activations. we pull activations from rule to activations map we store in
+     * working memory to facilitate activations removal when rule is removed
+     * from the memory
      * 
      */
     public Activation[] getActivations() {
-        final List list = this.workingMemory.getActivations();
-        return (Activation[]) list.toArray( new Activation[list.size()] );
+        final List list = this.workingMemory.getActivations( );
+        return (Activation[]) list.toArray( new Activation[list.size( )] );
     }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -24,7 +24,6 @@
 
 import org.drools.base.ClassObjectType;
 import org.drools.common.BetaNodeBinder;
-import org.drools.facttemplates.FactTemplate;
 import org.drools.facttemplates.FactTemplateObjectType;
 import org.drools.rule.And;
 import org.drools.rule.Column;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsFactHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsFactHandle.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsFactHandle.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -21,6 +21,7 @@
 import java.util.List;
 
 import org.drools.common.DefaultFactHandle;
+import org.drools.leaps.util.Table;
 
 /**
  * class container for each object asserted / retracted into the system
@@ -51,14 +52,14 @@
         if (this.notTuples == null) {
             this.notTuples = new LinkedList( );
         }
-        this.notTuples.add( new FactHandleTupleAssembly( tuple, index ) );
+        this.notTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.NOT, tuple, index ) );
     }
 
     protected void addExistsTuple( final LeapsTuple tuple, final int index ) {
         if (this.existsTuples == null) {
             this.existsTuples = new LinkedList( );
         }
-        this.existsTuples.add( new FactHandleTupleAssembly( tuple, index ) );
+        this.existsTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.EXISTS, tuple, index ) );
     }
 
     protected Iterator getActivatedTuples() {
@@ -81,4 +82,33 @@
         }
         return null;
     }
+    
+    protected void clearActivatedTuples() {
+        this.activatedTuples = null;
+    }
+    
+    protected void clearExistsTuples() {
+        this.existsTuples = null;
+    }
+    
+    protected void clearNotTuples() {
+        this.notTuples = null;
+    }
+    
+    private LinkedList hashes = null;
+    protected void addHash(Table table){
+        if(this.hashes == null){
+            this.hashes = new LinkedList();
+        }
+        this.hashes.add( table );
+    }
+    
+    protected void removeFromHash() {
+        if(this.hashes!= null){
+            for(Iterator it = this.hashes.iterator( ); it.hasNext( );){
+                ((Table)it.next( )).remove( this );
+            }
+            this.hashes.clear( );
+        }
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -125,6 +125,7 @@
      */
     public void addRule(final Rule rule) throws FactException,
                                         InvalidPatternException {
+        // checks rule validity
         super.addRule( rule );
 
         final List rules = LeapsBuilder.processRule( rule );
@@ -138,10 +139,7 @@
 
         // Iterate each workingMemory and attempt to fire any rules, that were
         // activated as a result of the new rule addition
-        for ( final Iterator it = this.getWorkingMemories().iterator(); it.hasNext(); ) {
-            final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) it.next();
-            workingMemory.fireAllRules();
-        }
+        // abstract rule base does it
     }
 
     public void removeRule(final Rule rule) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -29,7 +29,6 @@
 
 import org.drools.FactException;
 import org.drools.FactHandle;
-import org.drools.NoSuchFactObjectException;
 import org.drools.QueryResults;
 import org.drools.WorkingMemory;
 import org.drools.common.AbstractWorkingMemory;
@@ -107,80 +106,56 @@
             final FactTable factTable = (FactTable) tables.next( );
             // adding fact to container
             factTable.add( factHandle );
+            // iterate through unsatisfied exists
             for (final Iterator tuples = factTable.getTuplesIterator( ); tuples.hasNext( );) {
                 final LeapsTuple tuple = (LeapsTuple) tuples.next( );
 
-                final ColumnConstraints[] not = tuple.getLeapsRule( )
-                                                     .getNotColumnConstraints( );
-                for (int i = 0, length = not.length; i < length; i++) {
-                    final ColumnConstraints constraint = not[i];
-                    final Object columnClassObject = constraint.getClassType( );
-                    if (!tuple.isBlockingNotFactHandle( i )
-                            && ( ( objectClass.getClass( ) == Class.class
-                                    && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
-                                    && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
-                            && constraint.isAllowed( factHandle, tuple, this )) {
-                        tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
-                        ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
-                    }
-                }
-                // check exists constraints and activate constraints
-                final ColumnConstraints[] exists = tuple.getLeapsRule( )
-                                                        .getExistsColumnConstraints( );
-                for (int i = 0, length = exists.length; i < length; i++) {
-                    final ColumnConstraints constraint = exists[i];
-                    final Object columnClassObject = constraint.getClassType( );
-                    if (!tuple.isExistsFactHandle( i )
-                            && ( ( objectClass.getClass( ) == Class.class
-                                    && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
-                                    && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
-                            && constraint.isAllowed( factHandle, tuple, this )) {
-                        tuple.setExistsFactHandle( (LeapsFactHandle) factHandle, i );
-                        ( (LeapsFactHandle) factHandle ).addExistsTuple( tuple, i );
-                    }
-                }
+                TokenEvaluator.evaluateExistsConditions( tuple, tuple.getLeapsRule( ), this );
                 // check and see if we need activate
                 // activate only if tuple was not ready for it before
                 if (tuple.isReadyForActivation( )) {
                     // ready to activate
-                    tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
-                                                                  PropagationContext.ASSERTION,
-                                                                  tuple.getLeapsRule( )
-                                                                       .getRule( ),
-                                                                  null ) );
                     tuplesToAssert.add( tuple );
                 }
             }
-            for (Iterator tuples = tuplesToAssert.iterator( ); tuples.hasNext( );) {
-                LeapsTuple tuple = (LeapsTuple) tuples.next( );
+            for (final Iterator it = tuplesToAssert.iterator( ); it.hasNext( );) {
+                // ready to activate
+                final LeapsTuple tuple = (LeapsTuple) it.next( );
                 factTable.removeTuple( tuple );
+                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
+                                                              PropagationContext.ASSERTION,
+                                                              tuple.getLeapsRule( )
+                                                                   .getRule( ),
+                                                              null ) );
                 this.assertTuple( tuple );
             }
         }
-        // inspect all tuples for exists and not conditions and activate
+        // inspect all tuples for not conditions and activate
         // deactivate agenda items
         Activation[] activations = this.agenda.getActivations( );
         for (int k = 0; k < activations.length; k++) {
             boolean deActivate = false;
             LeapsTuple tuple = (LeapsTuple) activations[k].getTuple( );
             final ColumnConstraints[] not = tuple.getLeapsRule( ).getNotColumnConstraints( );
-            for (int i = 0, length = not.length; i < length; i++) {
+            for (int i = 0, length = not.length; !deActivate && i < length; i++) {
                 final ColumnConstraints constraint = not[i];
                 final Object columnClassObject = constraint.getClassType( );
-                if (!tuple.isBlockingNotFactHandle( i ) 
-                        && ( ( objectClass.getClass( ) == Class.class
-                                && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
-                                && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+                if (( ( objectClass.getClass( ) == Class.class
+                        && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+                        && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
                         && constraint.isAllowed( factHandle, tuple, this )) {
                     tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
                     ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
-                    if (!deActivate) {
-                        deActivate = true;
-                    }
+                    deActivate = true;
                 }
             }
             // check and see if we need de-activate
             if (deActivate) {
+                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
+                                                              PropagationContext.ASSERTION,
+                                                              tuple.getLeapsRule( )
+                                                                   .getRule( ),
+                                                              null ) );
                 if (tuple.getLeapsRule( ).getRule( ) instanceof Query) {
                     // put query results to the working memory
                     // location
@@ -209,8 +184,8 @@
          * leaps specific actions
          */
         // remove fact from all relevant fact tables container
-        for (final Iterator it = this.getFactTablesList( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
-                                     .iterator( ); it.hasNext( );) {
+        final Object objectClass = LeapsBuilder.getLeapsClassType( factHandle.getObject( ) );
+        for (final Iterator it = this.getFactTablesList( objectClass ).iterator( ); it.hasNext( );) {
             ( (FactTable) it.next( ) ).remove( factHandle );
         }
 
@@ -227,51 +202,10 @@
                 invalidateActivation( tuple );
             }
         }
-
-        // 1. remove fact for nots and exists tuples
-        final IdentityMap tuplesNotReadyForActivation = new IdentityMap( );
-        FactHandleTupleAssembly assembly;
-        LeapsTuple tuple;
-        Iterator it;
-        it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
-        if (it != null) {
-            for (; it.hasNext( );) {
-                assembly = (FactHandleTupleAssembly) it.next( );
-                tuple = assembly.getTuple( );
-                if (!tuple.isReadyForActivation( )) {
-                    tuplesNotReadyForActivation.put( tuple, tuple );
-                }
-                tuple.removeBlockingNotFactHandle( assembly.getIndex( ) );
-
-                TokenEvaluator.evaluateNotCondition( (LeapsFactHandle) factHandle,
-                // TokenEvaluator.evaluateNotCondition( new LeapsFactHandle(
-                // factHandle.getRecency( ) + 1,
-                                                     // new Object( ) ),
-                                                     assembly.getIndex( ),
-                                                     tuple,
-                                                     this );
-            }
-        }
-        it = ( (LeapsFactHandle) factHandle ).getExistsTupleAssemblies( );
-        if (it != null) {
-            for (; it.hasNext( );) {
-                assembly = (FactHandleTupleAssembly) it.next( );
-                tuple = assembly.getTuple( );
-                if (!tuple.isReadyForActivation( )) {
-                    tuplesNotReadyForActivation.put( tuple, tuple );
-                }
-                tuple.removeExistsFactHandle( assembly.getIndex( ) );
-                TokenEvaluator.evaluateExistsCondition( (LeapsFactHandle) factHandle,
-                // TokenEvaluator.evaluateExistsCondition( new LeapsFactHandle(
-                // factHandle.getRecency( ) + 1,
-                                                        // null ),
-                                                        assembly.getIndex( ),
-                                                        tuple,
-                                                        this );
-            }
-        }
-        // 2. assert all tuples that are ready for activation or cancel ones
+        ( (LeapsFactHandle) factHandle ).clearActivatedTuples( );
+        // assert all tuples that are ready for activation or cancel ones
         // that are no longer
+        Iterator it;
         final IteratorChain chain = new IteratorChain( );
         it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
         if (it != null) {
@@ -282,22 +216,30 @@
             chain.addIterator( it );
         }
         for (; chain.hasNext( );) {
-            tuple = ( (FactHandleTupleAssembly) chain.next( ) ).getTuple( );
+            FactHandleTupleAssembly tupleAssembly = ( (FactHandleTupleAssembly) chain.next( ) );
+            final LeapsTuple tuple = tupleAssembly.getTuple( );
+            if (tupleAssembly.getType( ) == FactHandleTupleAssembly.NOT) {
+                tuple.removeBlockingNotFactHandle( tupleAssembly.getIndex( ) );
+            }
+            else {
+                tuple.removeExistsFactHandle( tupleAssembly.getIndex( ) );
+            }
             // can assert only tuples that were not eligible for activation
             // before retraction
-            if (tuple.isReadyForActivation( )) {
-                // ready to activate
-                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
-                                                              PropagationContext.ASSERTION,
-                                                              tuple.getLeapsRule( )
-                                                                   .getRule( ),
-                                                              null ) );
-                this.getFactTable( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
-                    .removeTuple( tuple );
+            if (!TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+                                                                     tuple.getLeapsRule( ),
+                                                                     this )) {
+                // deactivate tuple that was activated inside of
+                // processAfterAllPositive
+                // bad design, need to rethink it
+                invalidateActivation( tuple );
+            }
+            else {
                 this.assertTuple( tuple );
             }
         }
-
+        ( (LeapsFactHandle) factHandle ).clearExistsTuples( );
+        ( (LeapsFactHandle) factHandle ).clearNotTuples( );
         // remove it from stack
         this.removeTokenFromStack( (LeapsFactHandle) factHandle );
     }
@@ -310,21 +252,20 @@
      */
     private final void invalidateActivation( final LeapsTuple tuple ) {
         final Activation activation = tuple.getActivation( );
-        if (!tuple.isReadyForActivation( ) && !tuple.isActivationNull( )) {
-            // invalidate agenda agendaItem
+        // tuple can already loose activation if another fact or exists fact was retracted
+        // or not fact added
+        if (activation != null) {
             if (activation.isActivated( )) {
                 activation.remove( );
-                getAgendaEventSupport( ).fireActivationCancelled( activation );
+                this.getAgendaEventSupport( ).fireActivationCancelled( activation );
             }
+
+            this.getTruthMaintenanceSystem( )
+                .removeLogicalDependencies( activation,
+                                            tuple.getContext( ),
+                                            tuple.getLeapsRule( ).getRule( ) );
             //
             tuple.setActivation( null );
-        }
-        if (activation != null) {
-            // remove logical dependency
-            this.tms.removeLogicalDependencies( activation,
-                                                tuple.getContext( ),
-                                                tuple.getLeapsRule( ).getRule( ) );
-
             // remove from rule / activaitons map
             FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule( ) );
             if (activations != null) {
@@ -344,70 +285,76 @@
                               final Rule rule,
                               final Activation activation ) throws FactException {
         try {
-            this.getLock( ).lock( );
-            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
-                                                                                      PropagationContext.MODIFICATION,
-                                                                                      rule,
-                                                                                      activation );
-
-            final int status = ( (InternalFactHandle) factHandle ).getEqualityKey( )
-                                                                  .getStatus( );
-
-            final Object originalObject = this.assertMap.remove( factHandle );
-            if (originalObject == null) {
-                throw new NoSuchFactObjectException( factHandle );
-            }
-            // 
-            // do subset of retractObject( )
-            //
+            this.lock.lock();
+            final int status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
-            if (handle.getId( ) == -1) {
-                // can't retract an already retracted handle
+            final Object originalObject = handle.getObject();
+
+            if ( handle.getId() == -1 || object == null ) {
+                // the handle is invalid, most likely already  retracted, so return
+                // and we cannot assert a null object
                 return;
             }
-            removePropertyChangeListener( handle );
 
-            doRetract( handle, propagationContext );
+            // set anyway, so that it updates the hashCodes
+            handle.setObject( object );
 
-            // Update the equality key, which maintains a list of stated
-            // FactHandles
-            final EqualityKey key = handle.getEqualityKey( );
+            // We only need to put objects, if its a new object
+            if ( originalObject != object ) {
+                this.assertMap.put( handle,
+                                    handle );
+            }
 
+            // the hashCode and equality has changed, so we must update the EqualityKey
+            EqualityKey key = handle.getEqualityKey();
             key.removeFactHandle( handle );
-            handle.setEqualityKey( null );
 
             // If the equality key is now empty, then remove it
-            if (key.isEmpty( )) {
+            if ( key.isEmpty() ) {
                 this.tms.remove( key );
             }
-            // produces NPE otherwise
-            this.handleFactory.destroyFactHandle( handle );
 
-            // 
-            // and now assert
-            //
-            /* check to see if this is a logically asserted object */
-            this.assertObject( object, false, ( status == EqualityKey.STATED ) ? false
-                    : true, rule, activation );
+            // now use an  existing  EqualityKey, if it exists, else create a new one
+            key = this.tms.get( object );
+            if ( key == null ) {
+                key = new EqualityKey( handle,
+                                       status );
+                this.tms.put( key );
+            } else {
+                key.addFactHandle( handle );
+            }
 
+            handle.setEqualityKey( key );
+
+            final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
+                                                                                      PropagationContext.MODIFICATION,
+                                                                                      rule,
+                                                                                      activation );
+            doRetract( handle, propagationContext );
+
+            this.handleFactory.increaseFactHandleRecency( handle );
+
+            doAssertObject( handle, object, propagationContext );
+
             this.workingMemoryEventSupport.fireObjectModified( propagationContext,
-                                                               handle,
-                                                               handle.getObject( ),
+                                                               factHandle,
+                                                               originalObject,
                                                                object );
 
-            if (!this.factQueue.isEmpty( )) {
-                propagateQueuedActions( );
+            if ( !this.factQueue.isEmpty() ) {
+                propagateQueuedActions();
             }
+        } finally {
+            this.lock.unlock();
         }
-        finally {
-            this.getLock( ).unlock( );
-        }
     }
 
     /**
      * ************* leaps section *********************
      */
     private long             idLastFireAllAt = -1;
+    
+    private boolean rulesAddedSinceLastFireAll = false;
 
     /**
      * algorithm stack.
@@ -521,6 +468,8 @@
     protected void addLeapsRules( final List rules ) {
         this.getLock( ).lock( );
         try {
+            this.rulesAddedSinceLastFireAll = true;
+            
             ArrayList ruleHandlesList;
             LeapsRule rule;
             LeapsRuleHandle ruleHandle;
@@ -630,6 +579,7 @@
         if (!this.firing) {
             try {
                 this.firing = true;
+                
                 boolean nothingToProcess = false;
                 while (!nothingToProcess) {
                     // check for the initial fact
@@ -637,13 +587,16 @@
                         LeapsRule rule = ( (LeapsRuleHandle) rulesIt.next( ) ).getLeapsRule( );
                         final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter( ),
                                                                                            PropagationContext.ASSERTION,
-                                                                                           null,
+                                                                                           null, //rule.getRule( ),
                                                                                            null );
-                        TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
-                                                                                            rule,
-                                                                                            context ),
-                                                                            rule,
-                                                                            this );
+                        final LeapsTuple tuple = new LeapsTuple( new LeapsFactHandle[0],
+                                                                 rule,
+                                                                 context );
+                        if (TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+                                                                                rule,
+                                                                                this )) {
+                            this.assertTuple( tuple );
+                        }
 
                     }
                     this.noPositiveColumnsRules.clear( );
@@ -708,6 +661,7 @@
                     }
                 }
                 // mark when method was called last time
+                this.rulesAddedSinceLastFireAll = false;
                 this.idLastFireAllAt = ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( );
                 // set all factTables to be reseeded
                 for (final Iterator it = this.factTables.values( ).iterator( ); it.hasNext( );) {
@@ -722,6 +676,10 @@
         }
     }
 
+    protected final boolean isRulesAddedSinceLastFireAll() {
+        return this.rulesAddedSinceLastFireAll;
+    }
+    
     protected final long getIdLastFireAllAt() {
         return this.idLastFireAllAt;
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -95,7 +95,9 @@
         if ( this.rulesIterator() != null ) {
             // starting with calling rulesIterator() to make sure that we picks
             // rules because fact can be asserted before rules added
-            final long levelId = this.workingMemory.getIdLastFireAllAt( );
+            final long levelId = ( this.workingMemory.isRulesAddedSinceLastFireAll( ) ) ? this.workingMemory.getIdLastFireAllAt( )
+                    : -1;
+            
             if (this.dominantFactHandle == null
                     || this.dominantFactHandle.getRecency( ) >= levelId) {
                 ret = this.rules.hasNext( );

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -189,9 +189,11 @@
                         // one check negative conditions and fire consequence
                         if (jj == stopIteratingCount) {
                             if (!skip) {
-                                if (processAfterAllPositiveConstraintOk( token.getTuple( ),
+                                final LeapsTuple tuple = token.getTuple( );
+                                if (processAfterAllPositiveConstraintOk( tuple,
                                                                          leapsRule,
                                                                          workingMemory )) {
+                                    workingMemory.assertTuple( tuple );
                                     return;
                                 }
                             }
@@ -230,25 +232,11 @@
         if (leapsRule.containsExistsColumns( )) {
             TokenEvaluator.evaluateExistsConditions( tuple, leapsRule, workingMemory );
         }
-        if (leapsRule.containsNotColumns( )) {
+        if (tuple.isReadyForActivation( ) && leapsRule.containsNotColumns( )) {
             TokenEvaluator.evaluateNotConditions( tuple, leapsRule, workingMemory );
         }
         // 
-        if (tuple.isReadyForActivation( )) {
-            // let agenda to do its work
-            workingMemory.assertTuple( tuple );
-            return true;
-        }
-        else {
-            // put tuple onto fact tables that might affect activation status
-            // via exists or not conditions
-            final Class[] classes = leapsRule.getExistsNotColumnsClasses( );
-            for (int i = 0, length = classes.length; i < length; i++) {
-                workingMemory.getFactTable( classes[i] ).addTuple( tuple );
-            }
-
-            return false;
-        }
+        return tuple.isReadyForActivation( );
     }
 
     /**
@@ -306,17 +294,15 @@
     final static void evaluateNotConditions( final LeapsTuple tuple,
                                              final LeapsRule rule,
                                              final LeapsWorkingMemory workingMemory ) {
+        // stops if exists
+        boolean done = false;
         final ColumnConstraints[] not = rule.getNotColumnConstraints( );
-        for (int i = 0, length = not.length; i < length; i++) {
+        for (int i = 0, length = not.length; i < length && !done; i++) {
             final ColumnConstraints constraint = not[i];
             // scan table starting at start fact handle
             final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
                                                              .reverseOrderIterator( tuple, constraint );
-//            .reverseOrderIterator( );
-            // stops if exists
-            boolean done = false;
             while (!done  && tableIterator.hasNext( )) {
-//                while (!done && tableIterator.hasNext( )) {
                 final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
                 // check constraint conditions
                 if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
@@ -329,103 +315,42 @@
     }
 
     /**
-     * To evaluate conditions above the water line that is supplied in the first
-     * argument
-     * 
-     * @param startFactHandle
-     * @param index
-     * @param tuple
-     * @param rule
-     * @param workingMemory
-     */
-    final static void evaluateNotCondition( final LeapsFactHandle startFactHandle,
-                                            final int index,
-                                            final LeapsTuple tuple,
-                                            final LeapsWorkingMemory workingMemory ) {
-        final LeapsRule rule = tuple.getLeapsRule( );
-        // scan table starting at start fact handle
-        final ColumnConstraints constraint = rule.getNotColumnConstraints( )[index];
-        final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                         .iteratorFromPositionToTableEnd( tuple, constraint, startFactHandle);
-//        .iteratorFromPositionToTableEnd( startFactHandle );
-//            .reverseOrderIterator( );
-        // stops if exists
-        boolean done = false;
-        while (!done && tableIterator.hasNext( )) {
-            final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
-            // check constraint conditions
-            if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
-                tuple.setBlockingNotFactHandle( factHandle, index );
-                factHandle.addNotTuple( tuple, index );
-                done = true;
-            }
-        }
-    }
-
-    /**
      * Check if any of the exists conditions are satisfied
      * 
      * @param tuple
      * @param memory
      * @throws Exception
      */
-    private final static void evaluateExistsConditions( final LeapsTuple tuple,
-                                                        final LeapsRule rule,
-                                                        final LeapsWorkingMemory workingMemory ) {
+    public final static void evaluateExistsConditions( final LeapsTuple tuple,
+                                                       final LeapsRule rule,
+                                                       final LeapsWorkingMemory workingMemory ) {
+        // stop if exists
+        boolean notFound = false;
+        boolean done = false;
         final ColumnConstraints[] exists = rule.getExistsColumnConstraints( );
-        for (int i = 0, length = exists.length; i < length; i++) {
+        for (int i = 0, length = exists.length; !notFound && i < length; i++) {
             final ColumnConstraints constraint = exists[i];
-            // scan table starting at start fact handle
-            final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                                             .reverseOrderIterator( tuple, constraint );
-//            .reverseOrderIterator( );
-            // stop if exists
-            boolean done = false;
-            while (!done && tableIterator.hasNext( )) {
-                final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
-                // check constraint conditions
-                if (constraint.isAllowed( factHandle,
-                                           tuple,
-                                           workingMemory ) ) {
-                    tuple.setExistsFactHandle( factHandle,
-                                               i );
-                    factHandle.addExistsTuple( tuple,
-                                               i );
-                    done = true;
+            if (!tuple.isExistsFactHandle( i )) {
+                // scan table starting at start fact handle
+                final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
+                                                                 .reverseOrderIterator( tuple,
+                                                                                        constraint );
+                done = false;
+                while (!done && tableIterator.hasNext( )) {
+                    final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
+                    // check constraint conditions
+                    if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
+                        tuple.setExistsFactHandle( factHandle, i );
+                        factHandle.addExistsTuple( tuple, i );
+                        done = true;
+                    }
                 }
+                if (!done) {
+                    notFound = true;
+                    workingMemory.getFactTable( constraint.getClassType( ) )
+                                 .addTuple( tuple );
+                }
             }
         }
     }
-
-    /**
-     * To evaluate conditions above the water line that is supplied in the first
-     * argument
-     * 
-     * @param startFactHandle
-     * @param index
-     * @param tuple
-     * @param rule
-     * @param workingMemory
-     */
-    final static void evaluateExistsCondition( final LeapsFactHandle startFactHandle,
-                                               final int index,
-                                               final LeapsTuple tuple,
-                                               final LeapsWorkingMemory workingMemory ) {
-        final LeapsRule rule = tuple.getLeapsRule( );
-        // scan table starting at start fact handle
-        final ColumnConstraints constraint = rule.getExistsColumnConstraints( )[index];
-        final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                                         .iteratorFromPositionToTableEnd( startFactHandle );
-        // stop if exists
-        boolean done = false;
-        while (!done && tableIterator.hasNext( )) {
-            final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
-            // check constraint conditions
-            if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
-                tuple.setExistsFactHandle( factHandle, index );
-                factHandle.addExistsTuple( tuple, index );
-                done = true;
-            }
-        }
-    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -86,7 +86,7 @@
 
             }
             catch (final NoSuchElementException nsee) {
-                // means map is empty
+                // means sub map is empty
                 this.headRecord.left = newRecord;
                 newRecord.right = this.headRecord;
                 this.headRecord = newRecord;
@@ -114,9 +114,8 @@
             try {
                 final TableRecord record = (TableRecord) this.set.tailSet( new TableRecord( object ) )
                                                                  .first( );
-
-                if (record != null) {
-                    if (record == this.headRecord) {
+                if (record != null && record.object == object) {
+                    if (record == this.headRecord ) {
                         if (record.right != null) {
                             this.headRecord = record.right;
                             this.headRecord.left = null;
@@ -124,8 +123,8 @@
                         else {
                             // single element in table being valid
                             // table is empty now
-                            this.headRecord = new TableRecord( null );
-                            this.tailRecord = this.headRecord;
+                            this.headRecord = null;
+                            this.tailRecord = null;
                             this.empty = true;
                         }
                     }
@@ -143,11 +142,15 @@
                     record.left = null;
                     record.right = null;
                 }
+                else {
+                    throw new NoSuchElementException();
+                }
                 this.count--;
                 //
                 this.set.remove( record );
             }
             catch (final NoSuchElementException nsee) {
+                throw nsee;
             }
         }
     }

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/LeapsMannersTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/LeapsMannersTest.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/LeapsMannersTest.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -32,7 +32,7 @@
         ruleBase.addPackage( this.pkg );
         final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
 
-        final InputStream is = getClass().getResourceAsStream( "/manners64.dat" );
+        final InputStream is = getClass().getResourceAsStream( "/manners128.dat" );
         final List list = getInputObjects( is );
         for ( final Iterator it = list.iterator(); it.hasNext(); ) {
             final Object object = it.next();

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java	2006-08-28 23:37:16 UTC (rev 5995)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java	2006-08-29 00:48:55 UTC (rev 5996)
@@ -30,10 +30,10 @@
         assertEquals(1, 
                      tms.getAssertMap().size() );        
         key = tms.get( string );
-        assertNotSame( fd, key.getFactHandle() );
+        assertSame( fd, key.getFactHandle() );
         assertNull( key.getOtherFactHandle() );
         
-        workingMemory.retractObject( key.getFactHandle() );
+        workingMemory.retractObject(fd);
         
         assertEquals(0, 
                      tms.getAssertMap().size() );        




More information about the jboss-svn-commits mailing list