[jboss-svn-commits] JBL Code SVN: r6901 - in labs/jbossrules/trunk/drools-core: . src/main/java/org/drools/common src/main/java/org/drools/reteoo src/main/java/org/drools/util src/test/java/org/drools/examples/manners

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Oct 18 18:04:54 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-10-18 18:04:45 -0400 (Wed, 18 Oct 2006)
New Revision: 6901

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/CompositeFieldIndexHashTable.java
Modified:
   labs/jbossrules/trunk/drools-core/.classpath
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityAssertMapComparator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityKeyComparator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/IdentityAssertMapComparator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/SingleBetaConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/MemoryVisitor.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/BaseMannersTest.java
Log:
JBRULES-526 Implement a CompositeIndex for Facts

Modified: labs/jbossrules/trunk/drools-core/.classpath
===================================================================
--- labs/jbossrules/trunk/drools-core/.classpath	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/.classpath	2006-10-18 22:04:45 UTC (rev 6901)
@@ -13,5 +13,6 @@
 	<classpathentry kind="var" path="M2_REPO/jung/jung/1.7.2/jung-1.7.2.jar"/>
 	<classpathentry kind="var" path="M2_REPO/xerces/xercesImpl/2.6.2/xercesImpl-2.6.2.jar"/>
 	<classpathentry kind="var" path="M2_REPO/junit/junit/3.8.1/junit-3.8.1.jar"/>
+	<classpathentry kind="lib" path="jess.jar"/>
 	<classpathentry kind="output" path="target/classes"/>
 </classpath>

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -36,11 +36,13 @@
 import org.drools.spi.AlphaNodeFieldConstraint;
 import org.drools.spi.FieldExtractor;
 import org.drools.spi.Tuple;
+import org.drools.util.CompositeFieldIndexHashTable;
 import org.drools.util.FactHashTable;
 import org.drools.util.FieldIndexHashTable;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
+import org.drools.util.CompositeFieldIndexHashTable.FieldIndex;
 
 public class DefaultBetaConstraints
     implements
@@ -158,9 +160,9 @@
         if ( this.indexed ) {
             Constraint constraint = ( Constraint ) this.constraints.getFirst();
             VariableConstraint variableConstraint = (VariableConstraint) constraint;
+            FieldIndex  index  = new  FieldIndex(variableConstraint.getFieldExtractor(), variableConstraint.getRequiredDeclarations()[0]);
             memory = new BetaMemory( new TupleHashTable(),
-                                     new FieldIndexHashTable( variableConstraint.getFieldExtractor(),
-                                                              variableConstraint.getRequiredDeclarations()[0] ) );
+                                     new CompositeFieldIndexHashTable( new FieldIndex[] { index }  ) );
         } else  {        
             memory = new BetaMemory( new TupleHashTable(),
                                      new FactHashTable() );

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DoubleBetaConstraints.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -17,7 +17,9 @@
  */
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import org.drools.WorkingMemory;
@@ -42,6 +44,8 @@
 import org.drools.util.LinkedListEntry;
 import org.drools.util.LinkedListNode;
 import org.drools.util.TupleHashTable;
+import org.drools.util.CompositeFieldIndexHashTable;
+import org.drools.util.CompositeFieldIndexHashTable.FieldIndex;
 
 public class DoubleBetaConstraints
     implements
@@ -59,21 +63,23 @@
     private ContextEntry                  context0;
     private ContextEntry                  context1;
 
-    private boolean                       indexed;
+    private boolean                       indexed0;
+    private boolean                       indexed1;
 
     public DoubleBetaConstraints(final BetaNodeFieldConstraint[] constraints) {
-        // find the first instrumental
-        for ( int i = 0, length = constraints.length; i < length; i++ ) {
-            if ( isIndexable( constraints[i] ) ) {
-                if ( i > 0) {
-                    // swap the constraint to the first position
-                    BetaNodeFieldConstraint temp = constraints[0];
-                    constraints[0] = constraints[i];
-                    constraints[i] = temp;
-                }
-                this.indexed = true;
-                break;
+        boolean i0 = isIndexable( constraints[0] );
+        boolean i1 = isIndexable( constraints[1] );
+
+        if ( i0 ) {
+            this.indexed0 = true;
+            if ( i1 ) {
+                this.indexed1 = true;
             }
+        } else if ( i1 ) {
+            this.indexed0 = true;
+            BetaNodeFieldConstraint temp = constraints[0];
+            constraints[0] = constraints[1];
+            constraints[1] = temp;
         }
 
         this.constraint0 = constraints[0];
@@ -112,9 +118,9 @@
      * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
      */
     public boolean isAllowedCachedLeft(Object object) {
-        return ( this.indexed || this.constraint0.isAllowedCachedLeft( context0,
-                                                     object ) ) && this.constraint1.isAllowedCachedLeft( context1,
-                                                                                                       object );
+        return (this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
+                                                                       object )) && (this.indexed1 || this.constraint1.isAllowedCachedLeft( context1,
+                                                                                                                                            object ));
     }
 
     /* (non-Javadoc)
@@ -127,7 +133,7 @@
     }
 
     public boolean isIndexed() {
-        return this.indexed;
+        return this.indexed0;
     }
 
     public boolean isEmpty() {
@@ -136,11 +142,27 @@
 
     public BetaMemory createBetaMemory() {
         BetaMemory memory;
-        if ( this.indexed ) {
+
+        List list = new ArrayList( 2 );
+        if ( this.indexed0 ) {
             VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+            FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                     variableConstraint.getRequiredDeclarations()[0] );
+            list.add( index );
+
+        }
+
+        if ( this.indexed1 ) {
+            VariableConstraint variableConstraint = (VariableConstraint) this.constraint1;
+            FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                     variableConstraint.getRequiredDeclarations()[0] );
+            list.add( index );
+        }
+
+        if ( !list.isEmpty() ) {
+            FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
             memory = new BetaMemory( new TupleHashTable(),
-                                     new FieldIndexHashTable( variableConstraint.getFieldExtractor(),
-                                                              variableConstraint.getRequiredDeclarations()[0] ) );
+                                     new CompositeFieldIndexHashTable( indexes ) );
         } else {
             memory = new BetaMemory( new TupleHashTable(),
                                      new FactHashTable() );
@@ -194,14 +216,14 @@
 
         final DoubleBetaConstraints other = (DoubleBetaConstraints) object;
 
-        if  ( this.constraint0 != other.constraint0 && this.constraint0.equals( other.constraint0 ) ) {
+        if ( this.constraint0 != other.constraint0 && this.constraint0.equals( other.constraint0 ) ) {
             return false;
         }
-        
-        if  ( this.constraint1 != other.constraint1 && this.constraint1.equals( other.constraint1 ) ) {
+
+        if ( this.constraint1 != other.constraint1 && this.constraint1.equals( other.constraint1 ) ) {
             return false;
         }
-        
+
         return true;
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityAssertMapComparator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityAssertMapComparator.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityAssertMapComparator.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -34,10 +34,18 @@
 
     public int hashCodeOf(final Object obj) {
         if ( obj.getClass() == this.factHandleClass ) {
-            return ((InternalFactHandle) obj).getObjectHashCode();
+            return rehash( ((InternalFactHandle) obj).getObjectHashCode() );
         }
-        return obj.hashCode();
+        return rehash( obj.hashCode() );
     }
+    
+    public int rehash(int h) {
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        return h;            
+    }
 
     /**
      * Special comparator  that  allows FactHandles to  be  keys, but always  checks

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityKeyComparator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityKeyComparator.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/EqualityKeyComparator.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -34,12 +34,15 @@
     }
     
     public int hashCodeOf(Object key) {
-        int h = key.hashCode();
+        return rehash( key.hashCode() );
+    }
+    
+    public int rehash(int h) {
         h += ~(h << 9);
         h ^= (h >>> 14);
         h += (h << 4);
         h ^= (h >>> 10);
-        return h;
+        return h;            
     }
 
     /**

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/IdentityAssertMapComparator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/IdentityAssertMapComparator.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/IdentityAssertMapComparator.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -34,10 +34,18 @@
 
     public int hashCodeOf(final Object obj) {
         if ( obj.getClass() == this.factHandleClass ) {
-            return ((InternalFactHandle) obj).getObjectHashCode();
+            return rehash( ((InternalFactHandle) obj).getObjectHashCode() );
         }
-        return obj.hashCode();
+        return rehash( obj.hashCode());
     }
+    
+    public int rehash(int h) {
+        h += ~(h << 9);
+        h ^= (h >>> 14);
+        h += (h << 4);
+        h ^= (h >>> 10);
+        return h;            
+    }
 
     /**
      * Special comparator that allows FactHandles to be keys, but always  checks

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/SingleBetaConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/SingleBetaConstraints.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/SingleBetaConstraints.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -23,11 +23,13 @@
 import org.drools.rule.ContextEntry;
 import org.drools.rule.VariableConstraint;
 import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.util.CompositeFieldIndexHashTable;
 import org.drools.util.FactHashTable;
 import org.drools.util.FieldIndexHashTable;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.TupleHashTable;
+import org.drools.util.CompositeFieldIndexHashTable.FieldIndex;
 
 public class SingleBetaConstraints
     implements
@@ -106,9 +108,9 @@
         BetaMemory memory;
         if ( this.indexed ) {
             VariableConstraint variableConstraint = (VariableConstraint) this.constraint;
+            FieldIndex  index  = new  FieldIndex(variableConstraint.getFieldExtractor(), variableConstraint.getRequiredDeclarations()[0]);
             memory = new BetaMemory( new TupleHashTable(),
-                                     new FieldIndexHashTable( variableConstraint.getFieldExtractor(),
-                                                              variableConstraint.getRequiredDeclarations()[0] ) );
+                                     new CompositeFieldIndexHashTable( new FieldIndex[] { index }  ) );
         } else {
             memory = new BetaMemory( new TupleHashTable(),
                                      new FactHashTable() );

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TripleBetaConstraints.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -17,7 +17,9 @@
  */
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import org.drools.WorkingMemory;
@@ -36,12 +38,14 @@
 import org.drools.spi.AlphaNodeFieldConstraint;
 import org.drools.spi.FieldExtractor;
 import org.drools.spi.Tuple;
+import org.drools.util.CompositeFieldIndexHashTable;
 import org.drools.util.FactHashTable;
 import org.drools.util.FieldIndexHashTable;
 import org.drools.util.LinkedList;
 import org.drools.util.LinkedListEntry;
 import org.drools.util.LinkedListNode;
 import org.drools.util.TupleHashTable;
+import org.drools.util.CompositeFieldIndexHashTable.FieldIndex;
 
 public class TripleBetaConstraints
     implements
@@ -61,31 +65,72 @@
     private ContextEntry                  context1;
     private ContextEntry                  context2;
 
-    private boolean                       indexed;
+    private boolean                       indexed0;
+    private boolean                       indexed1;
+    private boolean                       indexed2;
 
     public TripleBetaConstraints(final BetaNodeFieldConstraint[] constraints) {
-        // find the first instrumental
-        for ( int i = 0, length = constraints.length; i < length; i++ ) {
-            if ( isIndexable( constraints[i] ) ) {
-                if ( i > 0) {
-                    // swap the constraint to the first position
-                    BetaNodeFieldConstraint temp = constraints[0];
-                    constraints[0] = constraints[i];
-                    constraints[i] = temp;
-                }
-                this.indexed = true;
-                break;
+        //        // find the first instrumental
+        //        for ( int i = 0, length = constraints.length; i < length; i++ ) {
+        //            if ( isIndexable( constraints[i] ) ) {
+        //                if ( i > 0) {
+        //                    // swap the constraint to the first position
+        //                    BetaNodeFieldConstraint temp = constraints[0];
+        //                    constraints[0] = constraints[i];
+        //                    constraints[i] = temp;
+        //                }
+        //                this.indexed = true;
+        //                break;
+        //            }
+        //        }
+        //
+        //        this.constraint0 = constraints[0];
+        //        this.context0 = this.constraint0.getContextEntry();
+        //
+        //        this.constraint1 = constraints[1];
+        //        this.context1 = this.constraint1.getContextEntry();
+        //        
+        //        this.constraint2 = constraints[2];
+        //        this.context2 = this.constraint2.getContextEntry();     
+
+        boolean i0 = isIndexable( constraints[0] );
+        boolean i1 = isIndexable( constraints[1] );
+        boolean i2 = isIndexable( constraints[2] );
+
+        if ( i0 ) {
+            this.indexed0 = true;
+            if ( i1 ) {
+                this.indexed1 = true;
             }
+        } else if ( i1 ) {
+            this.indexed0 = true;
+            BetaNodeFieldConstraint temp = constraints[0];
+            constraints[0] = constraints[1];
+            constraints[1] = temp;
         }
+        
+        if  ( i2 ) {
+            if  (i0) {
+                this.indexed1 = true;
+                BetaNodeFieldConstraint temp = constraints[1];
+                constraints[1] = constraints[2];
+                constraints[2] = temp;                   
+            } else {
+                this.indexed0 = true;
+                BetaNodeFieldConstraint temp = constraints[0];
+                constraints[0] = constraints[2];
+                constraints[2] = temp;                
+            }
+        }
 
         this.constraint0 = constraints[0];
         this.context0 = this.constraint0.getContextEntry();
 
         this.constraint1 = constraints[1];
         this.context1 = this.constraint1.getContextEntry();
-        
+
         this.constraint2 = constraints[2];
-        this.context2 = this.constraint2.getContextEntry();        
+        this.context2 = this.constraint2.getContextEntry();
     }
 
     private boolean isIndexable(final BetaNodeFieldConstraint constraint) {
@@ -119,10 +164,15 @@
      * @see org.drools.common.BetaNodeConstraints#isAllowedCachedLeft(java.lang.Object)
      */
     public boolean isAllowedCachedLeft(Object object) {
-        return ( this.indexed || this.constraint0.isAllowedCachedLeft( context0,
-                                                                       object ) ) && this.constraint1.isAllowedCachedLeft( context1,
-                                                                                                       object ) && this.constraint2.isAllowedCachedLeft( context2,
-                                                                                                                                                         object );
+        //        return ( this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
+        //                                                                       object ) ) && this.constraint1.isAllowedCachedLeft( context1,
+        //                                                                                                       object ) && this.constraint2.isAllowedCachedLeft( context2,
+        //                                                                                                                                                         object );
+
+        return (this.indexed0 || this.constraint0.isAllowedCachedLeft( context0,
+                                                                       object )) && (this.indexed1 || this.constraint1.isAllowedCachedLeft( context1,
+                                                                                                                                            object )) && (this.indexed2 || this.constraint2.isAllowedCachedLeft( context2,
+                                                                                                                                                                                               object ) );
     }
 
     /* (non-Javadoc)
@@ -136,7 +186,7 @@
     }
 
     public boolean isIndexed() {
-        return this.indexed;
+        return this.indexed0;
     }
 
     public boolean isEmpty() {
@@ -144,12 +194,48 @@
     }
 
     public BetaMemory createBetaMemory() {
+        //        BetaMemory memory;
+        //        if ( this.indexed ) {
+        //            VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+        //            Index  index  = new  Index(variableConstraint.getFieldExtractor(), variableConstraint.getRequiredDeclarations()[0]);
+        //            memory = new BetaMemory( new TupleHashTable(),
+        //                                     new CompositeFieldIndexHashTable( new Index[] { index }  ) );
+        //        } else {
+        //            memory = new BetaMemory( new TupleHashTable(),
+        //                                     new FactHashTable() );
+        //        }
+        //
+        //        return memory;
+
         BetaMemory memory;
-        if ( this.indexed ) {
+
+        List list = new ArrayList( 2 );
+        if ( this.indexed0 ) {
             VariableConstraint variableConstraint = (VariableConstraint) this.constraint0;
+            FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                     variableConstraint.getRequiredDeclarations()[0] );
+            list.add( index );
+
+        }
+
+        if ( this.indexed1 ) {
+            VariableConstraint variableConstraint = (VariableConstraint) this.constraint1;
+            FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                     variableConstraint.getRequiredDeclarations()[0] );
+            list.add( index );
+        }
+        
+        if ( this.indexed2 ) {
+            VariableConstraint variableConstraint = (VariableConstraint) this.constraint2;
+            FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
+                                     variableConstraint.getRequiredDeclarations()[0] );
+            list.add( index );
+        }        
+
+        if ( !list.isEmpty() ) {
+            FieldIndex[] indexes = (FieldIndex[]) list.toArray( new FieldIndex[list.size()] );
             memory = new BetaMemory( new TupleHashTable(),
-                                     new FieldIndexHashTable( variableConstraint.getFieldExtractor(),
-                                                              variableConstraint.getRequiredDeclarations()[0] ) );
+                                     new CompositeFieldIndexHashTable( indexes ) );
         } else {
             memory = new BetaMemory( new TupleHashTable(),
                                      new FactHashTable() );
@@ -204,18 +290,18 @@
 
         final TripleBetaConstraints other = (TripleBetaConstraints) object;
 
-        if  ( this.constraint0 != other.constraint0 && this.constraint0.equals( other.constraint0 ) ) {
+        if ( this.constraint0 != other.constraint0 && this.constraint0.equals( other.constraint0 ) ) {
             return false;
         }
-        
-        if  ( this.constraint1 != other.constraint1 && this.constraint1.equals( other.constraint1 ) ) {
+
+        if ( this.constraint1 != other.constraint1 && this.constraint1.equals( other.constraint1 ) ) {
             return false;
         }
-        
-        if  ( this.constraint2 != other.constraint2 && this.constraint2.equals( other.constraint2 ) ) {
+
+        if ( this.constraint2 != other.constraint2 && this.constraint2.equals( other.constraint2 ) ) {
             return false;
-        }        
-        
+        }
+
         return true;
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/MemoryVisitor.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/MemoryVisitor.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/MemoryVisitor.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -8,15 +8,16 @@
 import org.drools.examples.manners.Context;
 import org.drools.reteoo.TerminalNode.TerminalNodeMemory;
 import org.drools.util.AbstractHashTable;
+import org.drools.util.CompositeFieldIndexHashTable;
 import org.drools.util.Entry;
 import org.drools.util.FactHashTable;
-import org.drools.util.FieldIndexHashTable;
+//import org.drools.util.FieldIndexHashTable;
 import org.drools.util.Iterator;
 import org.drools.util.ObjectHashMap;
 import org.drools.util.ReflectiveVisitor;
 import org.drools.util.TupleHashTable;
 import org.drools.util.AbstractHashTable.FactEntry;
-import org.drools.util.FieldIndexHashTable.FieldIndexEntry;
+import org.drools.util.CompositeFieldIndexHashTable.FieldIndexEntry;
 import org.drools.util.ObjectHashMap.ObjectEntry;
 
 public class MemoryVisitor extends ReflectiveVisitor {
@@ -131,9 +132,13 @@
         System.out.println( indent() + node );
         
         
-        BetaMemory memory  = ( BetaMemory ) this.workingMemory.getNodeMemory( node );   
-        checkObjectHashTable( memory.getObjectMemory() );          
-        checkTupleMemory( memory.getTupleMemory() );
+        try {
+            BetaMemory memory  = ( BetaMemory ) this.workingMemory.getNodeMemory( node );   
+            checkObjectHashTable( memory.getObjectMemory() );          
+            checkTupleMemory( memory.getTupleMemory() );
+        } catch ( Exception e ) {
+            e.printStackTrace();
+        }
         
         indent++;
         try {
@@ -152,10 +157,13 @@
 
     public void visitNotNode(final NotNode node) {
         System.out.println( indent() + node );
-        
-        BetaMemory memory  = ( BetaMemory ) this.workingMemory.getNodeMemory( node );   
-        checkObjectHashTable( memory.getObjectMemory() );          
-        checkTupleMemory( memory.getTupleMemory() );
+        try {
+            BetaMemory memory  = ( BetaMemory ) this.workingMemory.getNodeMemory( node );   
+            checkObjectHashTable( memory.getObjectMemory() );          
+            checkTupleMemory( memory.getTupleMemory() );
+        } catch ( Exception e ) {
+            e.printStackTrace();
+        }
 
         indent++;
         try {
@@ -196,8 +204,8 @@
     private void checkObjectHashTable(ObjectHashTable memory) {
         if ( memory instanceof FactHashTable) {
             checkFactHashTable( (FactHashTable )memory);
-        } else if ( memory instanceof FieldIndexHashTable ) {
-            checkFieldIndexHashTable( ( FieldIndexHashTable )memory);
+        } else if ( memory instanceof CompositeFieldIndexHashTable ) {
+            checkFieldIndexHashTable( ( CompositeFieldIndexHashTable )memory);
         } else {
             throw new RuntimeException( memory.getClass() + " should not be here" );
         }
@@ -222,7 +230,7 @@
         }  
     }
     
-    private void checkFieldIndexHashTable(FieldIndexHashTable memory) {
+    private void checkFieldIndexHashTable(CompositeFieldIndexHashTable memory) {
         Entry[] entries = memory.getTable();
         int factCount = 0;
         int bucketCount = 0;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/NotNode.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -58,7 +58,7 @@
     private static final long serialVersionUID = 320L;
     static int                notAssertObject  = 0;
     static int                notAssertTuple   = 0;
-
+    
     // ------------------------------------------------------------
     // Instance methods
     // ------------------------------------------------------------

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/Rete.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -21,14 +21,19 @@
 import java.util.List;
 
 import org.drools.FactException;
+import org.drools.FactHandle;
 import org.drools.RuleBaseConfiguration;
+import org.drools.base.ShadowProxy;
 import org.drools.common.BaseNode;
 import org.drools.common.InternalFactHandle;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.common.NodeMemory;
 import org.drools.facttemplates.Fact;
 import org.drools.facttemplates.FactImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
 import org.drools.spi.PropagationContext;
+import org.drools.util.FactHashTable;
 import org.drools.util.Iterator;
 import org.drools.util.ObjectHashMap;
 import org.drools.util.ObjectHashMap.ObjectEntry;
@@ -80,7 +85,7 @@
     // ------------------------------------------------------------
     // Instance methods
     // ------------------------------------------------------------
-
+    
     /**
      * This is the entry point into the network for all asserted Facts. Iterates a cache
      * of matching <code>ObjectTypdeNode</code>s asserting the Fact. If the cache does not

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -140,6 +140,18 @@
         return this.hashCode;
     }
     
+    public String toString() {
+        StringBuffer buffer = new StringBuffer();
+        
+        ReteTuple entry = this;
+        while ( entry != null ) {
+            //buffer.append( entry.handle );
+            buffer.append( entry.handle + "\n" );
+            entry = entry.parent;
+        }
+        return buffer.toString();
+    }
+    
     /**
      * We use this equals method to avoid the cast
      * @param tuple

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -179,6 +179,8 @@
     public interface ObjectComparator {
         public int hashCodeOf(Object object);
         
+        public int rehash(int hashCode);
+        
         public boolean equal(Object object1,
                              Object object2);
     }
@@ -242,12 +244,15 @@
         }
         
         public int hashCodeOf(Object key) {
-            int h = key.hashCode();
+            return rehash(  key.hashCode() ); 
+        }
+        
+        public int rehash(int h) {
             h += ~(h << 9);
             h ^= (h >>> 14);
             h += (h << 4);
             h ^= (h >>> 10);
-            return h;
+            return h;            
         }
 
         private InstanceEquals() {
@@ -270,12 +275,15 @@
         }
         
         public int hashCodeOf(Object key) {
-            int h = key.hashCode();
+            return rehash( key.hashCode() );
+        }
+        
+        public int rehash(int h) {
             h += ~(h << 9);
             h ^= (h >>> 14);
             h += (h << 4);
             h ^= (h >>> 10);
-            return h;
+            return h;            
         }
 
         private EqualityEquals() {

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/CompositeFieldIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/CompositeFieldIndexHashTable.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/CompositeFieldIndexHashTable.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -0,0 +1,411 @@
+/**
+ * 
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.reteoo.ObjectHashTable;
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.Declaration;
+import org.drools.spi.FieldExtractor;
+import org.drools.util.AbstractHashTable.ObjectComparator;
+import org.drools.util.ObjectHashMap.ObjectEntry;
+
+public class CompositeFieldIndexHashTable extends AbstractHashTable
+    implements
+    ObjectHashTable {
+    public static final int                   PRIME = 31;
+
+    private int                         startResult;
+
+    private FieldIndexHashTableIterator tupleValueIterator;
+
+    private int                         factSize;
+
+    private DefaultCompositeIndex       index;
+
+    public CompositeFieldIndexHashTable(FieldIndex[] index) {
+        this( 16,
+              0.75f,
+              index );
+    }
+
+    public CompositeFieldIndexHashTable(int capacity,
+                                        float loadFactor,
+                                        FieldIndex[] index) {
+        super( capacity,
+               loadFactor );
+
+        this.startResult = PRIME;
+        for ( int i = 0, length = index.length; i < length; i++ ) {
+            this.startResult += index[i].getExtractor().getIndex();
+        }
+        this.index = new DefaultCompositeIndex( index,
+                                                this.startResult,
+                                                this.comparator );
+    }
+
+    public Iterator iterator() {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support  iterator()" );
+    }
+
+    public Iterator iterator(ReteTuple tuple) {
+        if ( this.tupleValueIterator == null ) {
+            this.tupleValueIterator = new FieldIndexHashTableIterator();
+        }
+        FieldIndexEntry entry = (FieldIndexEntry) get( tuple );
+        this.tupleValueIterator.reset( (entry != null) ? entry.first : null );
+        return this.tupleValueIterator;
+    }
+
+    public boolean isIndexed() {
+        return true;
+    }
+
+    public Entry getBucket(Object object) {
+        int hashCode = this.index.hashCodeOf( object );
+        int index = indexOf( hashCode,
+                             table.length );
+
+        return (ObjectEntry) this.table[index];
+    }
+
+    /**
+     * Fast re-usable iterator
+     *
+     */
+    public static class FieldIndexHashTableIterator
+        implements
+        Iterator {
+        private Entry entry;
+
+        public FieldIndexHashTableIterator() {
+
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#next()
+         */
+        public Entry next() {
+            Entry current = this.entry;
+            this.entry = (this.entry != null) ? this.entry.getNext() : null;
+            return current;
+        }
+
+        /* (non-Javadoc)
+         * @see org.drools.util.Iterator#reset()
+         */
+        public void reset(Entry entry) {
+            this.entry = entry;
+        }
+    }
+
+    public boolean add(InternalFactHandle handle) {
+        FieldIndexEntry entry = getOrCreate( handle.getObject() );
+        entry.add( handle );
+        this.factSize++;
+        return true;
+    }
+
+    public boolean add(InternalFactHandle handle,
+                       boolean checkExists) {
+        throw new UnsupportedOperationException( "FieldIndexHashTable does not support add(InternalFactHandle handle, boolean checkExists)" );
+    }
+
+    public boolean remove(InternalFactHandle handle) {
+        Object object = handle.getObject();
+        int hashCode = this.index.hashCodeOf( object );
+
+        int index = indexOf( hashCode,
+                             table.length );
+
+        // search the table for  the Entry, we need to track previous  and next, so if the 
+        // Entry is empty after  its had the FactEntry removed, we must remove  it from the table
+        FieldIndexEntry previous = (FieldIndexEntry) this.table[index];
+        FieldIndexEntry current = previous;
+        while ( current != null ) {
+            FieldIndexEntry next = (FieldIndexEntry) current.next;
+            if ( current.matches( object,
+                                  hashCode ) ) {
+                current.remove( handle );
+                this.factSize--;
+                // If the FactEntryIndex is empty, then remove it from the hash map
+                if ( current.first == null ) {
+                    if ( previous == current ) {
+                        this.table[index] = next;
+                    } else {
+                        previous.next  = next;
+                    }
+                    current.next = null;
+                    this.size--;
+                }
+                return true;
+            }
+            previous = current;
+            current = next;
+        }
+        return false;
+    }
+
+    public boolean contains(InternalFactHandle handle) {
+        Object object = handle.getObject();
+        int hashCode = this.index.hashCodeOf( object );
+
+        int index = indexOf( hashCode,
+                             table.length );
+
+        FieldIndexEntry current = (FieldIndexEntry) this.table[index];
+        while ( current != null ) {
+            if ( current.matches( object,
+                                  hashCode ) ) {
+                return true;
+            }
+            current = (FieldIndexEntry) current.next;
+        }
+        return false;
+    }
+
+    public FieldIndexEntry get(ReteTuple tuple) {
+        int hashCode = this.index.hashCodeOf( tuple );
+
+        int index = indexOf( hashCode,
+                             table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        while ( entry != null ) {
+            if ( entry.matches( tuple,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.getNext();
+        }
+
+        return entry;
+    }
+
+    /**
+     * We use this method to aviod to table lookups for the same hashcode; which is what we would have to do if we did
+     * a get and then a create if the value is null.
+     * 
+     * @param value
+     * @return
+     */
+    private FieldIndexEntry getOrCreate(Object object) {
+        int hashCode = this.index.hashCodeOf( object );
+        int index = indexOf( hashCode,
+                             table.length );
+        FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+        while ( entry != null ) {
+            if ( entry.matches( object,
+                                hashCode ) ) {
+                return entry;
+            }
+            entry = (FieldIndexEntry) entry.next;
+        }
+
+        if ( entry == null ) {
+            entry = new FieldIndexEntry( this.index,
+                                         hashCode );
+            entry.next = this.table[index];
+            this.table[index] = entry;
+
+            if ( this.size++ >= this.threshold ) {
+                resize( 2 * this.table.length );
+            }
+        }
+        return entry;
+    }
+
+    public int size() {
+        return this.factSize;
+    }    
+
+    public static class FieldIndexEntry
+        implements
+        Entry {
+        private Entry          next;
+        private FactEntry      first;
+        private final int      hashCode;
+        private CompositeIndex index;
+
+        public FieldIndexEntry(CompositeIndex index,
+                               int hashCode) {
+            this.index = index;
+            this.hashCode = hashCode;
+        }
+
+        public Entry getNext() {
+            return next;
+        }
+
+        public void setNext(Entry next) {
+            this.next = next;
+        }
+
+        public FactEntry getFirst() {
+            return this.first;
+        }
+
+        public void add(InternalFactHandle handle) {
+            FactEntry entry = new FactEntry( handle );
+            entry.next = this.first;
+            this.first = entry;
+        }
+
+        public FactEntry get(InternalFactHandle handle) {
+            long id = handle.getId();
+            FactEntry current = first;
+            while ( current != null ) {
+                if ( current.handle.getId() == id ) {
+                    return current;
+                }
+                current = (FactEntry) current.next;
+            }
+            return null;
+        }
+
+        public FactEntry remove(InternalFactHandle handle) {
+            long id = handle.getId();
+
+            FactEntry previous = this.first;
+            FactEntry current = previous;
+            while ( current != null ) {
+                FactEntry next = (FactEntry) current.next;
+                if ( current.handle.getId() == id ) {
+                    if ( this.first == current ) {
+                        this.first = next;
+                    } else {
+                        previous.next = next;
+                    }
+                    current.next = null;
+                    return current;
+                }
+                previous = current;
+                current = next;
+            }
+            return current;
+        }
+
+        public boolean matches(Object object,
+                               int objectHashCode) {
+            return this.hashCode == objectHashCode && this.index.equal( this.first.getFactHandle().getObject(),
+                                                                        object );
+        }
+
+        public boolean matches(ReteTuple tuple,
+                               int tupleHashCode) {
+            return this.hashCode == tupleHashCode && this.index.equal( this.first.getFactHandle().getObject(),
+                                                                       tuple );
+        }
+
+        public int hashCode() {
+            return this.hashCode;
+        }
+
+        public boolean equals(Object object) {
+            FieldIndexEntry other = (FieldIndexEntry) object;
+            return this.hashCode == other.hashCode && this.index == other.index;
+        }
+    }
+
+    private static interface CompositeIndex {
+        public int hashCodeOf(ReteTuple tuple);
+
+        public int hashCodeOf(Object object);
+
+        public boolean equal(Object object1,
+                             Object object2);
+
+        public boolean equal(Object object1,
+                             ReteTuple tuple);
+    }
+
+    private static class DefaultCompositeIndex
+        implements
+        CompositeIndex {
+        private FieldIndex[]          indexes;
+        private int              startResult;
+        private ObjectComparator comparator;
+
+        public DefaultCompositeIndex(FieldIndex[] indexes,
+                                     int startResult,
+                                     ObjectComparator comparator) {
+            this.startResult = startResult;
+            this.indexes = indexes;
+            this.comparator = comparator;
+        }
+
+        public int hashCodeOf(Object object) {
+            int hashCode = startResult;
+            for ( int i = 0, length = this.indexes.length; i < length; i++ ) {
+                Object value = indexes[i].getExtractor().getValue( object );
+                hashCode += CompositeFieldIndexHashTable.PRIME * hashCode + ((value == null) ? 0 : value.hashCode() );
+            }
+            return this.comparator.rehash( hashCode );
+        }
+
+        public int hashCodeOf(ReteTuple tuple) {
+            int hashCode = startResult;
+            for ( int i = 0, length = this.indexes.length; i < length; i++ ) {
+                Object value = indexes[i].declaration.getValue( tuple.get( indexes[i].declaration ).getObject() );
+                hashCode += CompositeFieldIndexHashTable.PRIME * hashCode + ((value == null) ? 0 : value.hashCode() );
+            }
+            return this.comparator.rehash( hashCode );
+        }
+
+        public boolean equal(Object object1,
+                             ReteTuple tuple) {
+            for ( int i = 0, length = this.indexes.length; i < length; i++ ) {
+                Object value1 = indexes[i].extractor.getValue( object1 );
+                Object value2 = indexes[i].declaration.getValue( tuple.get( indexes[i].declaration ).getObject() );
+                if ( !this.comparator.equal( value1,
+                                             value2 ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public boolean equal(Object object1,
+                             Object object2) {
+            for ( int i = 0, length = this.indexes.length; i < length; i++ ) {
+                Object value1 = indexes[i].getExtractor().getValue( object1 );
+                Object value2 = indexes[i].getExtractor().getValue( object2 );
+                if ( !this.comparator.equal( value1,
+                                             value2 ) ) {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static class FieldIndex {
+        private FieldExtractor extractor;
+        private Declaration    declaration;
+
+        public FieldIndex(FieldExtractor extractor,
+                     Declaration declaration) {
+            super();
+            this.extractor = extractor;
+            this.declaration = declaration;
+        }
+
+        public Declaration getDeclaration() {
+            return declaration;
+        }
+
+        public void setDeclaration(Declaration declaration) {
+            this.declaration = declaration;
+        }
+
+        public FieldExtractor getExtractor() {
+            return extractor;
+        }
+
+        public void setExtractor(FieldExtractor extractor) {
+            this.extractor = extractor;
+        }
+    }
+}
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -161,7 +161,7 @@
 
         FieldIndexEntry current = (FieldIndexEntry) this.table[index];
         while ( current != null ) {
-            if ( hashCode == current.hashCode && value.equals( current.getValue() ) ) {
+            if ( hashCode == current.hashCode && this.comparator.equal( value, current.getValue() ) ) {
                 return  true;
             }
             current = (FieldIndexEntry) current.next;
@@ -178,7 +178,7 @@
         FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
 
         while ( entry != null ) {
-            if ( hashCode == entry.hashCode && value.equals( entry.getValue() ) ) {
+            if ( hashCode == entry.hashCode && this.comparator.equal( value, entry.getValue() ) ) {
                 return entry;
             }
             entry = (FieldIndexEntry) entry.getNext();
@@ -201,7 +201,8 @@
         FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
 
         while ( entry != null ) {
-            if ( hashCode == entry.hashCode && value.equals( entry.getValue() ) ) {
+            
+            if ( hashCode == entry.hashCode && this.comparator.equal( value, entry.getValue() ) ) {
                 return entry;
             }
             entry = (FieldIndexEntry) entry.next;

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/BaseMannersTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/BaseMannersTest.java	2006-10-18 21:57:43 UTC (rev 6900)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/examples/manners/BaseMannersTest.java	2006-10-18 22:04:45 UTC (rev 6901)
@@ -763,6 +763,7 @@
                                          context );
                     //System.err.println( "path done" + seating );
                 } catch ( Exception e ) {
+                    e.printStackTrace();
                     throw new ConsequenceException( e );
                 }
             }




More information about the jboss-svn-commits mailing list