[jboss-svn-commits] JBL Code SVN: r32454 - in labs/jbossrules/trunk/drools-core/src: test/java/org/drools/util and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Apr 6 22:38:02 EDT 2010


Author: mark.proctor at jboss.com
Date: 2010-04-06 22:38:02 -0400 (Tue, 06 Apr 2010)
New Revision: 32454

Added:
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/LeftTupleIndexHashTableIteratorTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/RightTupleIndexHashTableIteratorTest.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java
Log:
JBRULES-2108 Iterator only returns first bucket for shared table elements
-Added tests for both left and right indexes
-Rewrote iterators so they should now work.

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java	2010-04-06 18:02:34 UTC (rev 32453)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java	2010-04-07 02:38:02 UTC (rev 32454)
@@ -16,18 +16,18 @@
     implements
     LeftTupleMemory {
 
-    private static final long               serialVersionUID = 400L;
+    private static final long                         serialVersionUID = 400L;
 
-    public static final int                 PRIME            = 31;
+    public static final int                           PRIME            = 31;
 
-    private int                             startResult;
+    private int                                       startResult;
 
     private transient FieldIndexHashTableFullIterator tupleValueFullIterator;
 
-    private int                             factSize;
+    private int                                       factSize;
 
-    private Index                           index;
-    
+    private Index                                     index;
+
     public LeftTupleIndexHashTable() {
         // constructor for serialisation
     }
@@ -68,12 +68,13 @@
                 throw new IllegalArgumentException( "FieldIndexHashTable cannot use an index[] of length  great than 3" );
         }
     }
-    
-    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+
+    public void readExternal(ObjectInput in) throws IOException,
+                                            ClassNotFoundException {
         super.readExternal( in );
         startResult = in.readInt();
         factSize = in.readInt();
-        index = ( Index ) in.readObject();
+        index = (Index) in.readObject();
     }
 
     public void writeExternal(ObjectOutput out) throws IOException {
@@ -81,7 +82,7 @@
         out.writeInt( startResult );
         out.writeInt( factSize );
         out.writeObject( index );
-    }    
+    }
 
     public Iterator iterator() {
         if ( this.tupleValueFullIterator == null ) {
@@ -94,20 +95,20 @@
     public LeftTuple getFirst(final RightTuple rightTuple) {
         LeftTupleList bucket = get( rightTuple );
         if ( bucket != null ) {
-            return bucket.getFirst( ( LeftTuple ) null );
+            return bucket.getFirst( (LeftTuple) null );
         } else {
             return null;
         }
     }
-    
+
     public LeftTuple getFirst(final LeftTuple leftTuple) {
         final LeftTupleList bucket = get( leftTuple );
         if ( bucket != null ) {
-            return bucket.getFirst( ( LeftTuple ) null );
+            return bucket.getFirst( (LeftTuple) null );
         } else {
             return null;
-        }        
-    }    
+        }
+    }
 
     public boolean isIndexed() {
         return true;
@@ -132,33 +133,52 @@
         private Entry[]           table;
         private int               row;
         private int               length;
-        private Entry             entry;
+        private LeftTupleList     list;
+        private LeftTuple         leftTuple;
 
         public FieldIndexHashTableFullIterator(final AbstractHashTable hashTable) {
             this.hashTable = hashTable;
+            this.row = -1;
         }
 
         /* (non-Javadoc)
          * @see org.drools.util.Iterator#next()
          */
         public Object next() {
-            if ( this.entry == null ) {
-                // keep skipping rows until we come to the end, or find one that is populated
-                while ( this.entry == null ) {
-                    this.row++;
-                    if ( this.row == this.length ) {
-                        return null;
+            while ( true ) {                
+                if ( this.list == null ) {
+                    // check if there is a current bucket
+                    while ( this.list == null ) {
+                        // iterate while there is no current bucket, trying each array position
+                        this.list = (LeftTupleList) this.table[this.row];
+                        this.row++;
+                        
+                        if ( this.list != null ) {
+                            // we have a bucket so assign the frist LeftTuple and return
+                            this.leftTuple = (LeftTuple) this.list.getFirst( (LeftTuple) null );
+                            return this.leftTuple;
+                        } else if ( this.row == this.length ) {
+                            // we've scanned the whole table and nothing is left, so return null
+                            return null;
+                        }
+                        
                     }
-                    this.entry = (this.table[this.row] != null) ? ((LeftTupleList) this.table[this.row]).first : null;
                 }
-            } else {
-                this.entry = this.entry.getNext();
-                if ( this.entry == null ) {
-                    this.entry = (Entry) next();
+
+                this.leftTuple = (LeftTuple) this.leftTuple.getNext();
+                if ( this.leftTuple != null ) {
+                    // we have a next tuple so return
+                    return this.leftTuple;
+                } else {
+                    this.list = (LeftTupleList) this.list.getNext();
+                    // try the next bucket if we have a shared array position
+                    if ( this.list != null ) {
+                        // if we have another bucket, assign the first LeftTuple and return
+                        this.leftTuple = (LeftTuple) this.list.getFirst( (LeftTuple) null );
+                        return this.leftTuple;
+                    }
                 }
             }
-
-            return this.entry;
         }
 
         public void remove() {
@@ -171,8 +191,9 @@
         public void reset() {
             this.table = this.hashTable.getTable();
             this.length = this.table.length;
-            this.row = -1;
-            this.entry = null;
+            this.row = 0;
+            this.list = null;
+            this.leftTuple = null;
         }
     }
 
@@ -182,7 +203,7 @@
         for ( int i = 0; i < this.table.length; i++ ) {
             LeftTupleList bucket = (LeftTupleList) this.table[i];
             while ( bucket != null ) {
-                LeftTuple entry = (LeftTuple) bucket.getFirst( ( LeftTuple ) null );
+                LeftTuple entry = (LeftTuple) bucket.getFirst( (LeftTuple) null );
                 while ( entry != null ) {
                     result[index++] = entry;
                     entry = (LeftTuple) entry.getNext();
@@ -360,5 +381,5 @@
 
         return builder.toString();
     }
-    
+
 }
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java	2010-04-06 18:02:34 UTC (rev 32453)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java	2010-04-07 02:38:02 UTC (rev 32454)
@@ -45,7 +45,7 @@
 
         this.startResult = RightTupleIndexHashTable.PRIME;
         for ( int i = 0, length = index.length; i < length; i++ ) {
-            this.startResult = RightTupleIndexHashTable.PRIME * this.startResult + index[i].getExtractor().getIndex();
+            this.startResult += RightTupleIndexHashTable.PRIME * this.startResult + index[i].getExtractor().getIndex();
         }
 
         switch ( index.length ) {
@@ -141,7 +141,8 @@
         private Entry[]           table;
         private int               row;
         private int               length;
-        private Entry             entry;
+        private RightTupleList     list;
+        private RightTuple         rightTuple;
 
         public FieldIndexHashTableFullIterator(final AbstractHashTable hashTable) {
             this.hashTable = hashTable;
@@ -151,23 +152,40 @@
          * @see org.drools.util.Iterator#next()
          */
         public Object next() {
-            if ( this.entry == null ) {
-                // keep skipping rows until we come to the end, or find one that is populated
-                while ( this.entry == null ) {
-                    this.row++;
-                    if ( this.row == this.length ) {
-                        return null;
+            while ( true ) {                
+                if ( this.list == null ) {
+                    // check if there is a current bucket
+                    while ( this.list == null ) {
+                        // iterate while there is no current bucket, trying each array position
+                        this.list = (RightTupleList) this.table[this.row];
+                        this.row++;
+                        
+                        if ( this.list != null ) {
+                            // we have a bucket so assign the frist LeftTuple and return
+                            this.rightTuple = (RightTuple) this.list.getFirst( (RightTuple) null );
+                            return this.rightTuple;
+                        } else if ( this.row == this.length ) {
+                            // we've scanned the whole table and nothing is left, so return null
+                            return null;
+                        }
+                        
                     }
-                    this.entry = (this.table[this.row] != null) ? ((RightTupleList) this.table[this.row]).first : null;
                 }
-            } else {
-                this.entry = this.entry.getNext();
-                if ( this.entry == null ) {
-                    this.entry = (Entry) next();
+
+                this.rightTuple = (RightTuple) this.rightTuple.getNext();
+                if ( this.rightTuple != null ) {
+                    // we have a next tuple so return
+                    return this.rightTuple;
+                } else {
+                    this.list = (RightTupleList) this.list.getNext();
+                    // try the next bucket if we have a shared array position
+                    if ( this.list != null ) {
+                        // if we have another bucket, assign the first LeftTuple and return
+                        this.rightTuple = (RightTuple) this.list.getFirst( (RightTuple) null );
+                        return this.rightTuple;
+                    }
                 }
             }
-
-            return this.entry;
         }
 
         public void remove() {
@@ -180,8 +198,9 @@
         public void reset() {
             this.table = this.hashTable.getTable();
             this.length = this.table.length;
-            this.row = -1;
-            this.entry = null;
+            this.row = 0;
+            this.list = null;
+            this.rightTuple = null;
         }
     }
 

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/LeftTupleIndexHashTableIteratorTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/LeftTupleIndexHashTableIteratorTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/LeftTupleIndexHashTableIteratorTest.java	2010-04-07 02:38:02 UTC (rev 32454)
@@ -0,0 +1,207 @@
+package org.drools.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.base.ClassFieldAccessorCache;
+import org.drools.base.ClassFieldAccessorStore;
+import org.drools.base.ClassObjectType;
+import org.drools.base.evaluators.ComparableEvaluatorsDefinition;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.base.evaluators.MatchesEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.evaluators.SetEvaluatorsDefinition;
+import org.drools.base.evaluators.SoundslikeEvaluatorsDefinition;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.SingleBetaConstraints;
+import org.drools.core.util.Entry;
+import org.drools.core.util.Iterator;
+import org.drools.core.util.LeftTupleIndexHashTable;
+import org.drools.core.util.LeftTupleList;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.LeftTuple;
+import org.drools.rule.Declaration;
+import org.drools.rule.Pattern;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.InternalReadAccessor;
+
+
+public class LeftTupleIndexHashTableIteratorTest extends TestCase {
+
+    public static EvaluatorRegistry registry = new EvaluatorRegistry();
+    static {
+        registry.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
+    }    
+    
+    public void test1() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "d", Operator.EQUAL, "this", Foo.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+        
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+
+        BetaConstraints betaConstraints = null;
+        
+        betaConstraints = new SingleBetaConstraints(constraints, config);
+        
+        BetaMemory betaMemory = betaConstraints.createBetaMemory( config );
+        
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        StatefulSession ss = rb.newStatefulSession();
+        
+        InternalFactHandle fh1 = (InternalFactHandle) ss.insert( new Foo( "brie", 1) );
+        InternalFactHandle fh2 = (InternalFactHandle) ss.insert( new Foo( "brie", 1) );
+        InternalFactHandle fh3 = (InternalFactHandle) ss.insert( new Foo( "soda", 1) );
+        InternalFactHandle fh4 = (InternalFactHandle) ss.insert( new Foo( "soda", 1) );
+        InternalFactHandle fh5 = (InternalFactHandle) ss.insert( new Foo( "bread", 3) );
+        InternalFactHandle fh6 = (InternalFactHandle) ss.insert( new Foo( "bread", 3) );
+        InternalFactHandle fh7 = (InternalFactHandle) ss.insert( new Foo( "cream", 3) );
+        InternalFactHandle fh8 = (InternalFactHandle) ss.insert( new Foo( "gorda", 15) );
+        InternalFactHandle fh9 = (InternalFactHandle) ss.insert( new Foo( "beer", 16) );
+        
+        InternalFactHandle fh10 = (InternalFactHandle) ss.insert( new Foo( "mars", 0) );
+        InternalFactHandle fh11 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        InternalFactHandle fh12 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        InternalFactHandle fh13 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh1, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh2, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh3, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh4, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh5, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh6, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh7, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh8, null, true ) );
+        betaMemory.getLeftTupleMemory().add( new LeftTuple( fh9, null, true ) );
+        
+        LeftTupleIndexHashTable hashTable = (LeftTupleIndexHashTable) betaMemory.getLeftTupleMemory();
+        // can't create a 0 hashCode, so forcing 
+        LeftTupleList leftTupleList = new LeftTupleList();
+        leftTupleList.add( new LeftTuple( fh10, null, true ) );
+        hashTable.getTable()[0] = leftTupleList;        
+        leftTupleList = new LeftTupleList();
+        leftTupleList.add( new LeftTuple( fh11, null, true ) );
+        leftTupleList.add( new LeftTuple( fh12, null, true ) );
+        leftTupleList.add( new LeftTuple( fh13, null, true ) );
+        ((LeftTupleList)hashTable.getTable()[0]).setNext( leftTupleList );
+        
+        Entry[] table = hashTable.getTable();
+        List list = new ArrayList();
+        for ( int i = 0; i < table.length; i++ ) {
+            if ( table[i] != null ) {
+                List entries = new ArrayList();
+                entries.add( i );
+                Entry entry = table[i];
+                while ( entry != null ) {
+                    entries.add( entry );
+                    entry = entry.getNext();
+                }
+                list.add( entries.toArray() );
+            }
+        }        
+        assertEquals( 5, list.size() );
+        
+        Object[] entries = (Object[]) list.get( 0 );
+        assertEquals( 0, entries[0]);
+        assertEquals( 3, entries.length );
+        
+        entries = (Object[]) list.get( 1 );
+        assertEquals( 67, entries[0]);
+        assertEquals( 3, entries.length );
+        
+        entries = (Object[]) list.get( 2 );
+        assertEquals( 84, entries[0]);
+        assertEquals( 2, entries.length );
+        
+        entries = (Object[]) list.get( 3 );
+        assertEquals( 114, entries[0]);
+        assertEquals( 2, entries.length );
+        
+        entries = (Object[]) list.get( 4 );
+        assertEquals( 118, entries[0]);  
+        assertEquals( 3, entries.length );
+        
+        
+        //System.out.println( entries );
+
+        list = new ArrayList<LeftTuple>();
+        Iterator it = betaMemory.getLeftTupleMemory().iterator();
+        for ( LeftTuple leftTuple = ( LeftTuple ) it.next(); leftTuple != null; leftTuple = ( LeftTuple ) it.next() ) {
+            list.add( leftTuple );
+        }
+        
+        assertEquals( 13, list.size() );
+             
+    }
+    
+    protected BetaNodeFieldConstraint getConstraint(String identifier,
+                                                    Operator operator,
+                                                    String fieldName,
+                                                    Class clazz) {
+        ClassFieldAccessorStore store = new ClassFieldAccessorStore();
+        store.setClassFieldAccessorCache( new ClassFieldAccessorCache( Thread.currentThread().getContextClassLoader() ) );
+        store.setEagerWire( true );
+        InternalReadAccessor extractor = store.getReader( clazz,
+                                                          fieldName,
+                                                          getClass().getClassLoader() );
+        Declaration declaration = new Declaration( identifier,
+                                                   extractor,
+                                                   new Pattern( 0,
+                                                                new ClassObjectType( clazz ) ) );
+        Evaluator evaluator = registry.getEvaluatorDefinition( operator.getOperatorString() ).getEvaluator( extractor.getValueType(),
+                                                                                                            operator.getOperatorString(),
+                                                                                                            operator.isNegated(),
+                                                                                                            null );
+        return new VariableConstraint( extractor,
+                                       declaration,
+                                       evaluator );
+    }    
+    
+    public static class Foo {
+        private String val;
+        private int hashCode;
+        
+        public Foo(String val, int hashCode) {
+            this.val = val;
+            this.hashCode = hashCode;
+        }
+
+        public String getVal() {
+            return val;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( obj == null ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            Foo other = (Foo) obj;
+            if ( hashCode != other.hashCode ) return false;
+            if ( val == null ) {
+                if ( other.val != null ) return false;
+            } else if ( !val.equals( other.val ) ) return false;
+            return true;
+        }
+        
+        
+    }
+       
+}

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/RightTupleIndexHashTableIteratorTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/RightTupleIndexHashTableIteratorTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/RightTupleIndexHashTableIteratorTest.java	2010-04-07 02:38:02 UTC (rev 32454)
@@ -0,0 +1,210 @@
+package org.drools.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.base.ClassFieldAccessorCache;
+import org.drools.base.ClassFieldAccessorStore;
+import org.drools.base.ClassObjectType;
+import org.drools.base.evaluators.ComparableEvaluatorsDefinition;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.EvaluatorRegistry;
+import org.drools.base.evaluators.MatchesEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.evaluators.SetEvaluatorsDefinition;
+import org.drools.base.evaluators.SoundslikeEvaluatorsDefinition;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.SingleBetaConstraints;
+import org.drools.core.util.Entry;
+import org.drools.core.util.Iterator;
+import org.drools.core.util.LeftTupleIndexHashTable;
+import org.drools.core.util.LeftTupleList;
+import org.drools.core.util.RightTupleIndexHashTable;
+import org.drools.core.util.RightTupleList;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.LeftTuple;
+import org.drools.reteoo.RightTuple;
+import org.drools.rule.Declaration;
+import org.drools.rule.Pattern;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.InternalReadAccessor;
+
+
+public class RightTupleIndexHashTableIteratorTest extends TestCase {
+
+    public static EvaluatorRegistry registry = new EvaluatorRegistry();
+    static {
+        registry.addEvaluatorDefinition( new EqualityEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new ComparableEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SetEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new MatchesEvaluatorsDefinition() );
+        registry.addEvaluatorDefinition( new SoundslikeEvaluatorsDefinition() );
+    }    
+    
+    public void test1() {
+        VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "d", Operator.EQUAL, "this", Foo.class );
+        VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+        
+        RuleBaseConfiguration config = new RuleBaseConfiguration();
+
+        BetaConstraints betaConstraints = null;
+        
+        betaConstraints = new SingleBetaConstraints(constraints, config);
+        
+        BetaMemory betaMemory = betaConstraints.createBetaMemory( config );
+        
+        RuleBase rb = RuleBaseFactory.newRuleBase();
+        StatefulSession ss = rb.newStatefulSession();
+        
+        InternalFactHandle fh1 = (InternalFactHandle) ss.insert( new Foo( "brie", 1) );
+        InternalFactHandle fh2 = (InternalFactHandle) ss.insert( new Foo( "brie", 1) );
+        InternalFactHandle fh3 = (InternalFactHandle) ss.insert( new Foo( "soda", 1) );
+        InternalFactHandle fh4 = (InternalFactHandle) ss.insert( new Foo( "soda", 1) );
+        InternalFactHandle fh5 = (InternalFactHandle) ss.insert( new Foo( "bread", 3) );
+        InternalFactHandle fh6 = (InternalFactHandle) ss.insert( new Foo( "bread", 3) );
+        InternalFactHandle fh7 = (InternalFactHandle) ss.insert( new Foo( "cream", 3) );
+        InternalFactHandle fh8 = (InternalFactHandle) ss.insert( new Foo( "gorda", 15) );
+        InternalFactHandle fh9 = (InternalFactHandle) ss.insert( new Foo( "beer", 16) );
+        
+        InternalFactHandle fh10 = (InternalFactHandle) ss.insert( new Foo( "mars", 0) );
+        InternalFactHandle fh11 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        InternalFactHandle fh12 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        InternalFactHandle fh13 = (InternalFactHandle) ss.insert( new Foo( "snicker", 0) );
+        
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh1, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh2, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh3, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh4, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh5, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh6, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh7, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh8, null ) );
+        betaMemory.getRightTupleMemory().add( new RightTuple( fh9, null ) );
+        
+        RightTupleIndexHashTable hashTable = (RightTupleIndexHashTable) betaMemory.getRightTupleMemory();
+        // can't create a 0 hashCode, so forcing 
+        RightTupleList rightTupleList = new RightTupleList();
+        rightTupleList.add( new RightTuple( fh10, null) );
+        hashTable.getTable()[0] = rightTupleList;        
+        rightTupleList = new RightTupleList();
+        rightTupleList.add( new RightTuple( fh11, null ) );
+        rightTupleList.add( new RightTuple( fh12, null ) );
+        rightTupleList.add( new RightTuple( fh13, null ) );
+        ((RightTupleList)hashTable.getTable()[0]).setNext( rightTupleList );
+        
+        Entry[] table = hashTable.getTable();
+        List list = new ArrayList();
+        for ( int i = 0; i < table.length; i++ ) {
+            if ( table[i] != null ) {
+                List entries = new ArrayList();
+                entries.add( i );
+                Entry entry = table[i];
+                while ( entry != null ) {
+                    entries.add( entry );
+                    entry = entry.getNext();
+                }
+                list.add( entries.toArray() );
+            }
+        }        
+        assertEquals( 5, list.size() );
+        
+        Object[] entries = (Object[]) list.get( 0 );
+        assertEquals( 0, entries[0]);
+        assertEquals( 3, entries.length );
+        
+        entries = (Object[]) list.get( 1 );
+        assertEquals( 67, entries[0]);
+        assertEquals( 3, entries.length );
+        
+        entries = (Object[]) list.get( 2 );
+        assertEquals( 84, entries[0]);
+        assertEquals( 2, entries.length );
+        
+        entries = (Object[]) list.get( 3 );
+        assertEquals( 114, entries[0]);
+        assertEquals( 2, entries.length );
+        
+        entries = (Object[]) list.get( 4 );
+        assertEquals( 118, entries[0]);  
+        assertEquals( 3, entries.length );
+        
+        
+        //System.out.println( entries );
+
+        list = new ArrayList<LeftTuple>();
+        Iterator it = betaMemory.getRightTupleMemory().iterator();
+        for ( RightTuple rightTuple = ( RightTuple ) it.next(); rightTuple != null; rightTuple = ( RightTuple ) it.next() ) {
+            list.add( rightTuple );
+        }
+        
+        assertEquals( 13, list.size() );
+             
+    }
+    
+    protected BetaNodeFieldConstraint getConstraint(String identifier,
+                                                    Operator operator,
+                                                    String fieldName,
+                                                    Class clazz) {
+        ClassFieldAccessorStore store = new ClassFieldAccessorStore();
+        store.setClassFieldAccessorCache( new ClassFieldAccessorCache( Thread.currentThread().getContextClassLoader() ) );
+        store.setEagerWire( true );
+        InternalReadAccessor extractor = store.getReader( clazz,
+                                                          fieldName,
+                                                          getClass().getClassLoader() );
+        Declaration declaration = new Declaration( identifier,
+                                                   extractor,
+                                                   new Pattern( 0,
+                                                                new ClassObjectType( clazz ) ) );
+        Evaluator evaluator = registry.getEvaluatorDefinition( operator.getOperatorString() ).getEvaluator( extractor.getValueType(),
+                                                                                                            operator.getOperatorString(),
+                                                                                                            operator.isNegated(),
+                                                                                                            null );
+        return new VariableConstraint( extractor,
+                                       declaration,
+                                       evaluator );
+    }    
+    
+    public static class Foo {
+        private String val;
+        private int hashCode;
+        
+        public Foo(String val, int hashCode) {
+            this.val = val;
+            this.hashCode = hashCode;
+        }
+
+        public String getVal() {
+            return val;
+        }
+
+        @Override
+        public int hashCode() {
+            return hashCode;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if ( this == obj ) return true;
+            if ( obj == null ) return false;
+            if ( getClass() != obj.getClass() ) return false;
+            Foo other = (Foo) obj;
+            if ( hashCode != other.hashCode ) return false;
+            if ( val == null ) {
+                if ( other.val != null ) return false;
+            } else if ( !val.equals( other.val ) ) return false;
+            return true;
+        }
+        
+        
+    }
+       
+}



More information about the jboss-svn-commits mailing list