[jboss-svn-commits] JBL Code SVN: r6288 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/util test/java/org/drools/util
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Sep 18 18:20:32 EDT 2006
Author: mark.proctor at jboss.com
Date: 2006-09-18 18:20:26 -0400 (Mon, 18 Sep 2006)
New Revision: 6288
Added:
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/main/java/org/drools/util/ObjectHashMap.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexHashTableTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/ObjectHashMapTest.java
Removed:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/DroolsMap.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexEntry.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java
Modified:
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexEntryTest.java
Log:
Added: 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-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -0,0 +1,188 @@
+/**
+ *
+ */
+package org.drools.util;
+
+import java.io.Serializable;
+
+public abstract class AbstractHashTable implements Serializable {
+ static final int MAX_CAPACITY = 1 << 30;
+
+ protected int size;
+ protected int threshold;
+ protected float loadFactor;
+
+ protected boolean checkExists;
+ protected ObjectComparator comparator;
+
+ protected Entry[] table;
+
+ public AbstractHashTable() {
+ this( 16,
+ 0.75f );
+ }
+
+ public AbstractHashTable(int capacity,
+ float loadFactor) {
+ this.loadFactor = loadFactor;
+ this.threshold = (int) (capacity * loadFactor);
+ this.table = new Entry[capacity];
+ this.comparator = EqualityEquals.getInstance();
+ this.checkExists = false;
+ }
+
+
+ public void setCheckExists(boolean checkExists) {
+ this.checkExists = checkExists;
+ }
+
+ public void setComparator(ObjectComparator comparator) {
+ this.comparator = comparator;
+ }
+
+ protected void resize(int newCapacity) {
+ Entry[] oldTable = this.table;
+ int oldCapacity = oldTable.length;
+ if ( oldCapacity == MAX_CAPACITY ) {
+ this.threshold = Integer.MAX_VALUE;
+ return;
+ }
+
+ Entry[] newTable = new Entry[newCapacity];
+
+ for ( int i = 0; i < this.table.length; i++ ) {
+ Entry entry = this.table[i];
+ if ( entry == null ) {
+ continue;
+ }
+ this.table[i] = null;
+ Entry next = null;
+ while ( entry != null ) {
+ next = entry.getNext();
+
+ int index = indexOf( entry.hashCode(), newTable.length );
+ entry.setNext( newTable[index] );
+ newTable[index] = entry;
+
+ entry = next;
+ }
+ }
+
+ this.table = newTable;
+ this.threshold = (int) (newCapacity * this.loadFactor);
+ }
+
+// public void add(Entry entry) {
+// int index = indexOf( entry.hashCode(), table.length );
+//
+//
+// boolean exists = false;
+//
+// // scan the linked entries to see if it exists
+// if ( !checkExists ) {
+// Entry current = this.table[index];
+// int hashCode = entry.hashCode();
+// while ( current != null ) {
+// if ( hashCode == current.hashCode() && entry.equals( current ) ) {
+// exists = true;
+// }
+// }
+// }
+//
+// if( exists == false ) {
+// entry.setNext( this.table[index] );
+// this.table[index] = entry;
+//
+// if ( this.size++ >= this.threshold ) {
+// resize( 2 * this.table.length );
+// }
+// }
+//
+// }
+//
+// public Entry get(Entry entry) {
+// int index = indexOf( entry.hashCode(), table.length );
+// Entry current = this.table[index];
+// while ( current != null ) {
+// if ( entry.hashCode() == current.hashCode() && entry.equals( current ) ) {
+// return current;
+// }
+// current = current.getNext();
+// }
+// return null;
+// }
+//
+// public Entry remove(Entry entry) {
+// int index = indexOf( entry.hashCode(), table.length );
+// Entry previous = this.table[index];
+// Entry current = previous;
+// int hashCode = entry.hashCode();
+// while ( current != null ) {
+// Entry next = current.getNext();
+// if ( hashCode == current.hashCode() && entry.equals( current ) ) {
+// if( previous == current ) {
+// this.table[index] = next;
+// previous.setNext( next );
+// }
+// current.setNext( null );
+// this.size--;
+// return current;
+// }
+// previous = current;
+// current = next;
+// }
+// return current;
+// }
+
+ public Entry getBucket(int hashCode) {
+ return this.table[ indexOf( hashCode, table.length ) ];
+ }
+
+ public int size() {
+ return this.size;
+ }
+
+ protected int indexOf(int hashCode, int dataSize) {
+ int index = hashCode % dataSize;
+ if ( index < 0 ) {
+ index = index * -1;
+ }
+ return index;
+ }
+
+ public interface ObjectComparator {
+ public boolean equal(Object object1, Object object2);
+ }
+
+ public static class InstanceEquals implements ObjectComparator {
+ public static ObjectComparator INSTANCE = new InstanceEquals();
+
+ public static ObjectComparator getInstance() {
+ return INSTANCE;
+ }
+
+ private InstanceEquals() {
+
+ }
+
+ public boolean equal(Object object1, Object object2) {
+ return object1 == object2;
+ }
+ }
+
+ public static class EqualityEquals implements ObjectComparator {
+ public static ObjectComparator INSTANCE = new EqualityEquals();
+
+ public static ObjectComparator getInstance() {
+ return INSTANCE;
+ }
+
+ private EqualityEquals() {
+
+ }
+
+ public boolean equal(Object object1, Object object2) {
+ return object1.equals( object2 );
+ }
+ }
+}
\ No newline at end of file
Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/DroolsMap.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/DroolsMap.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/DroolsMap.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -1,139 +0,0 @@
-/**
- *
- */
-package org.drools.util;
-
-public class DroolsMap {
- static final int MAX_CAPACITY = 1 << 30;
-
- protected int size;
- protected int threshold;
- protected float loadFactor;
-
- protected boolean checkExists;
-
- protected Entry[] table;
-
- public DroolsMap() {
- this( 16,
- 0.75f );
- }
-
- public DroolsMap(int capacity,
- float loadFactor) {
- this.loadFactor = loadFactor;
- this.threshold = (int) (capacity * loadFactor);
- this.table = new Entry[capacity];
- }
-
- protected void resize(int newCapacity) {
- Entry[] oldTable = this.table;
- int oldCapacity = oldTable.length;
- if ( oldCapacity == MAX_CAPACITY ) {
- this.threshold = Integer.MAX_VALUE;
- return;
- }
-
- Entry[] newTable = new Entry[newCapacity];
-
- for ( int i = 0; i < this.table.length; i++ ) {
- Entry entry = this.table[i];
- if ( entry == null ) {
- continue;
- }
- this.table[i] = null;
- Entry next = null;
- while ( entry != null ) {
- next = entry.getNext();
-
- int index = indexOf( entry.hashCode(), newTable.length );
- entry.setNext( newTable[index] );
- newTable[index] = entry;
-
- entry = next;
- }
- }
-
- this.table = newTable;
- this.threshold = (int) (newCapacity * this.loadFactor);
- }
-
- public void add(Entry entry) {
- int index = indexOf( entry.hashCode(), table.length );
-
-
- boolean exists = false;
-
- // scan the linked entries to see if it exists
- if ( !checkExists ) {
- Entry current = this.table[index];
- int hashCode = entry.hashCode();
- while ( current != null ) {
- if ( hashCode == current.hashCode() && entry.equals( current ) ) {
- exists = true;
- }
- }
- }
-
- if( exists == false ) {
- entry.setNext( this.table[index] );
- this.table[index] = entry;
-
- if ( this.size++ >= this.threshold ) {
- resize( 2 * this.table.length );
- }
- }
-
- }
-
- public Entry get(Entry entry) {
- int index = indexOf( entry.hashCode(), table.length );
- Entry current = this.table[index];
- while ( current != null ) {
- if ( entry.hashCode() == current.hashCode() && entry.equals( current ) ) {
- return current;
- }
- current = current.getNext();
- }
- return null;
- }
-
- public Entry remove(Entry entry) {
- int index = indexOf( entry.hashCode(), table.length );
- Entry previous = this.table[index];
- Entry current = previous;
- int hashCode = entry.hashCode();
- while ( current != null ) {
- Entry next = current.getNext();
- if ( hashCode == current.hashCode() && entry.equals( current ) ) {
- if( previous == current ) {
- this.table[index] = next;
- previous.setNext( next );
- }
- current.setNext( null );
- this.size--;
- return current;
- }
- previous = current;
- current = next;
- }
- return current;
- }
-
- public Entry getBucket(int hashCode) {
- int index = indexOf( hashCode, table.length );
- return this.table[index];
- }
-
- public int size() {
- return this.size;
- }
-
- protected int indexOf(int hashCode, int length) {
- int index = hashCode % length;
- if ( index < 0 ) {
- index = index * -1;
- }
- return index;
- }
-}
\ No newline at end of file
Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexEntry.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexEntry.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexEntry.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -1,88 +0,0 @@
-/**
- *
- */
-package org.drools.util;
-
-import org.drools.common.InternalFactHandle;
-import org.drools.spi.FieldExtractor;
-
-public class FieldIndexEntry extends BaseEntry {
- FactEntry first;
-
- private final int hashCode;
- final int fieldIndex;
- private final FieldExtractor extractor;
-
- public FieldIndexEntry(FieldExtractor extractor,
- int fieldIndex,
- int hashCode) {
- this.extractor = extractor;
- this.fieldIndex = fieldIndex;
- this.hashCode = hashCode;
- }
-
- public FactEntry getFirst() {
- return this.first;
- }
-
- public void add(InternalFactHandle handle) {
- FactEntry entry = new FactEntry( handle );
- entry.setNext( this.first );
- this.first = entry;
- }
-
- public FactEntry get(InternalFactHandle handle) {
- long id = handle.getId();
- FactEntry current = first;
- while ( current != null ) {
- if ( current.getFactHandle().getId() == id ) {
- return current;
- }
- current = ( FactEntry ) current.getNext();
- }
- 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.getNext();
- if ( current.getFactHandle().getId() == id ) {
- this.first = next;
- previous.setNext( next );
- current.setNext( null );
- return current;
- }
- previous = current;
- current = next;
- }
- return current;
- }
-
- public String toString() {
- return this.extractor.toString();
- }
-
- public int fieldIndex() {
- return this.fieldIndex;
- }
-
- public Object getValue() {
- if ( this.first == null ) {
- return null;
- }
- return this.extractor.getValue( this.first.getFactHandle().getObject() );
- }
-
- public int hashCode() {
- return this.hashCode;
- }
-
- public boolean equals(Object object) {
- FieldIndexEntry other = ( FieldIndexEntry ) object;
- return this.hashCode == other.hashCode && this.fieldIndex == other.fieldIndex;
- }
-}
\ No newline at end of file
Copied: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java (from rev 6269, labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java)
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java 2006-09-18 13:40:02 UTC (rev 6269)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexHashTable.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -0,0 +1,213 @@
+/**
+ *
+ */
+package org.drools.util;
+
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.FieldExtractor;
+
+public class FieldIndexHashTable extends AbstractHashTable {
+ private int fieldIndex;
+ private FieldExtractor extractor;
+
+ private final int PRIME = 31;
+
+ private final int startResult;
+
+ public FieldIndexHashTable(int fieldIndex,
+ FieldExtractor extractor) {
+ this( 16,
+ 0.75f,
+ fieldIndex,
+ extractor );
+ }
+
+ public FieldIndexHashTable(int capacity,
+ float loadFactor,
+ int fieldIndex,
+ FieldExtractor extractor) {
+ super( capacity,
+ loadFactor );
+ this.fieldIndex = fieldIndex;
+ this.extractor = extractor;
+
+ this.startResult = PRIME + this.fieldIndex;
+ }
+
+ public void add(InternalFactHandle handle) {
+ FieldIndexEntry entry = getOrCreate( this.extractor.getValue( handle.getObject() ) );
+ entry.add( handle );
+ }
+
+ public void remove(InternalFactHandle handle) {
+ Object value = this.extractor.getValue( handle.getObject() );
+ int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
+
+ 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 ( hashCode == current.hashCode && value.equals( current.getValue() ) ) {
+ current.remove( handle );
+ // If the FactEntryIndex is empty, then remove it from the hash map
+ if ( current.first == null ) {
+ if( previous == current ) {
+ this.table[index] = next;
+ previous.next = next;
+ }
+ current.next = null;
+ this.size--;
+ }
+ return;
+ }
+ previous = current;
+ current = next;
+ }
+ }
+
+ public FieldIndexEntry get(Object value) {
+ int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
+
+ int index = indexOf( hashCode, table.length );
+ FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+ while ( entry != null ) {
+ if ( hashCode == entry.hashCode && value.equals( entry.getValue() ) ) {
+ 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
+ */
+ public FieldIndexEntry getOrCreate(Object value) {
+ int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
+ int index = indexOf( hashCode, table.length );
+ FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
+
+ while ( entry != null ) {
+ if ( hashCode == entry.hashCode && value.equals( entry.getValue() ) ) {
+ return entry;
+ }
+ entry = (FieldIndexEntry) entry.next;
+ }
+
+ if ( entry == null ) {
+ entry = new FieldIndexEntry( this.extractor,
+ fieldIndex,
+ hashCode );
+ entry.next = this.table[index];
+ this.table[index] = entry;
+
+ if ( this.size++ >= this.threshold ) {
+ resize( 2 * this.table.length );
+ }
+ }
+ return entry;
+ }
+
+ public static class FieldIndexEntry implements Entry {
+ private Entry next;
+ FactEntry first;
+ private final int hashCode;
+ private final int fieldIndex;
+ private final FieldExtractor extractor;
+
+ public FieldIndexEntry(FieldExtractor extractor,
+ int fieldIndex,
+ int hashCode) {
+ this.extractor = extractor;
+ this.fieldIndex = fieldIndex;
+ 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.setNext( this.first );
+ this.first = entry;
+ }
+
+ public FactEntry get(InternalFactHandle handle) {
+ long id = handle.getId();
+ FactEntry current = first;
+ while ( current != null ) {
+ if ( current.getFactHandle().getId() == id ) {
+ return current;
+ }
+ current = (FactEntry) current.getNext();
+ }
+ 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.getNext();
+ if ( current.getFactHandle().getId() == id ) {
+ if ( this.first == current ) {
+ this.first = next;
+ } else {
+ previous.setNext( next );
+ }
+ current.setNext( null );
+ return current;
+ }
+ previous = current;
+ current = next;
+ }
+ return current;
+ }
+
+ public String toString() {
+ return this.extractor.toString();
+ }
+
+ public int fieldIndex() {
+ return this.fieldIndex;
+ }
+
+ public Object getValue() {
+ if ( this.first == null ) {
+ return null;
+ }
+ return this.extractor.getValue( this.first.getFactHandle().getObject() );
+ }
+
+ public int hashCode() {
+ return this.hashCode;
+ }
+
+ public boolean equals(Object object) {
+ FieldIndexEntry other = (FieldIndexEntry) object;
+ return this.hashCode == other.hashCode && this.fieldIndex == other.fieldIndex;
+ }
+ }
+}
\ No newline at end of file
Deleted: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FieldIndexMap.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -1,121 +0,0 @@
-/**
- *
- */
-package org.drools.util;
-
-import org.drools.common.InternalFactHandle;
-import org.drools.spi.FieldExtractor;
-
-public class FieldIndexMap extends DroolsMap {
- private int fieldIndex;
- private FieldExtractor extractor;
-
- private final int PRIME = 31;
-
- private final int startResult;
-
- public FieldIndexMap(int fieldIndex,
- FieldExtractor extractor) {
- this( 16,
- 0.75f,
- fieldIndex,
- extractor );
- }
-
- public FieldIndexMap(int capacity,
- float loadFactor,
- int fieldIndex,
- FieldExtractor extractor) {
- super( capacity,
- loadFactor );
- this.fieldIndex = fieldIndex;
- this.extractor = extractor;
-
- this.startResult = PRIME + this.fieldIndex;
- }
-
- public void add(InternalFactHandle handle) {
- FieldIndexEntry entry = getOrCreate( this.extractor.getValue( handle.getObject() ) );
- entry.add( handle );
- }
-
- public void remove(InternalFactHandle handle) {
- Object value = this.extractor.getValue( handle.getObject() );
- int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
-
- 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.getNext();
- if ( hashCode == current.hashCode() && value.equals( current.getValue() ) ) {
- current.remove( handle );
- // If the FactEntryIndex is empty, then remove it from the hash map
- if ( current.first == null ) {
- if( previous == current ) {
- this.table[index] = next;
- previous.setNext( next );
- }
- current.setNext( null );
- this.size--;
- }
- return;
- }
- previous = current;
- current = next;
- }
- }
-
- public FieldIndexEntry get(Object value) {
- int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
-
- int index = indexOf( hashCode, table.length );
- FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
-
- while ( entry != null ) {
- if ( hashCode == entry.hashCode() && value.equals( entry.getValue() ) ) {
- 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 value) {
- int hashCode = PRIME * startResult + ((value == null) ? 0 : value.hashCode());
- int index = indexOf( hashCode, table.length );
- FieldIndexEntry entry = (FieldIndexEntry) this.table[index];
-
- while ( entry != null ) {
- if ( hashCode == entry.hashCode() && value.equals( entry.getValue() ) ) {
- return entry;
- }
- entry = (FieldIndexEntry) entry.getNext();
- }
-
- if ( entry == null ) {
- entry = new FieldIndexEntry( this.extractor,
- fieldIndex,
- hashCode );
- entry.setNext( this.table[index] );
- this.table[index] = entry;
-
- if ( this.size++ >= this.threshold ) {
- resize( 2 * this.table.length );
- }
- }
- return entry;
- }
-}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -0,0 +1,167 @@
+/**
+ *
+ */
+package org.drools.util;
+
+public class ObjectHashMap extends AbstractHashTable {
+ public ObjectHashMap() {
+ this( 16,
+ 0.75f );
+ }
+
+ public ObjectHashMap(int capacity,
+ float loadFactor) {
+ super( capacity,
+ loadFactor );
+ }
+
+ public Object put(Object key,
+ Object value) {
+ int hashCode = hash( key );
+ int index = indexOf( hashCode,
+ table.length );
+
+ // scan the linked entries to see if it exists
+ if ( checkExists ) {
+ ObjectEntry current = (ObjectEntry) this.table[index];
+ while ( current != null ) {
+ if ( hashCode == current.hashCode && comparator.equal( key,
+ current.key ) ) {
+ Object oldValue = current.value;
+ current.value = value;
+ return oldValue;
+ }
+ }
+ }
+
+ // We aren't checking the key exists, or it didn't find the key
+ ObjectEntry entry = new ObjectEntry( key,
+ value,
+ hashCode );
+ entry.next = this.table[index];
+ this.table[index] = entry;
+
+ if ( this.size++ >= this.threshold ) {
+ resize( 2 * this.table.length );
+ }
+ return null;
+ }
+
+ public Object get(Object key) {
+ int hashCode = hash( key );
+ int index = indexOf( hashCode,
+ table.length );
+
+ ObjectEntry current = (ObjectEntry) this.table[index];
+ while ( current != null ) {
+ if ( hashCode == current.hashCode && comparator.equal( key,
+ current.key ) ) {
+ return current.value;
+ }
+ current = (ObjectEntry) current.getNext();
+ }
+ return null;
+ }
+
+ public Object remove(Object key) {
+ int hashCode = hash( key );
+ int index = indexOf( hashCode,
+ table.length );
+
+ ObjectEntry previous = (ObjectEntry) this.table[index];
+ ObjectEntry current = previous;
+ while ( current != null ) {
+ ObjectEntry next = (ObjectEntry) current.getNext();
+ if ( hashCode == current.hashCode && comparator.equal( key,
+ current.key ) ) {
+ if ( previous == current ) {
+ this.table[index] = next;
+ } else {
+ previous.setNext( next );
+ }
+ current.setNext( null );
+ this.size--;
+ return current;
+ }
+ previous = current;
+ current = next;
+ }
+ return current;
+ }
+
+ public Entry getBucket(int hashCode) {
+ int h = hashCode;
+ h += ~(h << 9);
+ h ^= (h >>> 14);
+ h += (h << 4);
+ h ^= (h >>> 10);
+
+ return this.table[ indexOf( h, table.length ) ];
+ }
+
+ public int hash(Object key) {
+ int h = key.hashCode();
+ h += ~(h << 9);
+ h ^= (h >>> 14);
+ h += (h << 4);
+ h ^= (h >>> 10);
+ return h;
+ }
+
+ protected int indexOf(int hashCode,
+ int dataSize) {
+ return hashCode & (dataSize - 1);
+ }
+
+ private static class ObjectEntry
+ implements
+ Entry {
+ private Object key;
+
+ private Object value;
+
+ private int hashCode;
+
+ private Entry next;
+
+ public ObjectEntry(Object key,
+ Object value,
+ int hashCode) {
+ this.key = key;
+ this.value = value;
+ this.hashCode = hashCode;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+
+ public Object getKey() {
+ return key;
+ }
+
+ public Entry getNext() {
+ return this.next;
+ }
+
+ public void setNext(Entry next) {
+ this.next = next;
+ }
+
+ public int hashCode() {
+ return this.key.hashCode() ^ this.value.hashCode();
+ }
+
+ public boolean equals(Object object) {
+ if ( object == this ) {
+ return true;
+ }
+
+ // assumes we never have null or wrong class
+
+ ObjectEntry other = (ObjectEntry) object;
+ return this.key.equals( other.key ) && this.value.equals( other.value );
+ }
+ }
+}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexEntryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexEntryTest.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexEntryTest.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -4,6 +4,7 @@
import org.drools.base.ClassFieldExtractor;
import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalFactHandle;
+import org.drools.util.FieldIndexHashTable.FieldIndexEntry;
import junit.framework.TestCase;
Copied: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexHashTableTest.java (from rev 6284, labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java)
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java 2006-09-18 19:14:03 UTC (rev 6284)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexHashTableTest.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -0,0 +1,314 @@
+package org.drools.util;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.util.FieldIndexHashTable.FieldIndexEntry;
+
+public class FieldIndexHashTableTest extends TestCase {
+
+ public void testSingleEntry() throws Exception {
+ ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ assertEquals(0, map.size() );
+
+ assertNull( map.get( "cheddar" ) );
+
+ Cheese stilton1 = new Cheese("stilton", 35);
+ InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
+ map.add( stiltonHandle1 );
+
+ assertEquals(1, map.size() );
+ assertEquals( 1, tablePopulationSize( map ) );
+
+ FieldIndexEntry stiltonEntry = map.get( "stilton" );
+ assertSame( stiltonHandle1, stiltonEntry.getFirst().getFactHandle() );
+ assertNull( stiltonEntry.getFirst().getNext() );
+ }
+
+ public void testTwoDifferentEntries() throws Exception {
+ ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ assertEquals(0, map.size() );
+
+ Cheese stilton1 = new Cheese("stilton", 35);
+ InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
+ map.add( stiltonHandle1 );
+
+ Cheese cheddar1 = new Cheese("cheddar", 35);
+ InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
+ map.add( cheddarHandle1 );
+
+ assertEquals(2, map.size() );
+ assertEquals( 2, tablePopulationSize( map ) );
+
+ FieldIndexEntry stiltonEntry = map.get( "stilton" );
+ assertSame( stiltonHandle1, stiltonEntry.getFirst().getFactHandle() );
+ assertNull( stiltonEntry.getFirst().getNext() );
+
+ FieldIndexEntry cheddarEntry = map.get( "cheddar" );
+ assertSame( cheddarHandle1, cheddarEntry.getFirst().getFactHandle() );
+ assertNull( cheddarEntry.getFirst().getNext() );
+ }
+
+ public void testTwoEqualEntries() throws Exception {
+ ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ assertEquals(0, map.size() );
+
+ Cheese stilton1 = new Cheese("stilton", 35);
+ InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
+ map.add( stiltonHandle1 );
+
+ Cheese cheddar1 = new Cheese("cheddar", 35);
+ InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
+ map.add( cheddarHandle1 );
+
+ Cheese stilton2 = new Cheese("stilton", 81);
+ InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3, stilton2 );
+ map.add( stiltonHandle2 );
+
+ // Two siltons are in the same index bucket, so it won't increase the map size
+ assertEquals(2, map.size() );
+ assertEquals( 2, tablePopulationSize( map ) );
+
+ // Check they are correctly chained to the same FieldIndexEntry
+ FieldIndexEntry stiltonEntry = map.get( "stilton" );
+ assertSame( stiltonHandle2, stiltonEntry.getFirst().getFactHandle() );
+ assertSame( stiltonHandle1, ((FactEntry)stiltonEntry.getFirst().getNext()).getFactHandle() );
+ }
+
+ public void testTwoDifferentEntriesSameHashCode() throws Exception {
+ ClassFieldExtractor extractor = new ClassFieldExtractor(TestClass.class, "object");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ TestClass c1 = new TestClass( 0, new TestClass( 20, "stilton" ) );
+ InternalFactHandle ch1 = new DefaultFactHandle( 1, c1 );
+
+ map.add( ch1 );
+
+ TestClass c2 = new TestClass( 0, new TestClass( 20, "cheddar" ) );
+ InternalFactHandle ch2 = new DefaultFactHandle( 2, c2 );
+ map.add( ch2 );
+
+ // same hashcode, but different values, so it should result in a size of 2
+ assertEquals(2, map.size() );
+
+ // however both are in the same table bucket
+ assertEquals( 1, tablePopulationSize( map ) );
+
+
+ // this table bucket will have two FieldIndexEntries, as they are actually two different values
+ FieldIndexEntry entry = (FieldIndexEntry) getEntries( map )[0];
+
+ assertEquals( c2.getObject(), entry.getValue());
+ assertEquals( c1.getObject(), ((FieldIndexEntry) entry.getNext()).getValue());
+ }
+
+ public void testRemove() throws Exception {
+ ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ assertEquals(0, map.size() );
+
+ Cheese stilton1 = new Cheese("stilton", 35);
+ InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
+ map.add( stiltonHandle1 );
+
+ Cheese cheddar1 = new Cheese("cheddar", 35);
+ InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
+ map.add( cheddarHandle1 );
+
+ Cheese stilton2 = new Cheese("stilton", 81);
+ InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3, stilton2 );
+ map.add( stiltonHandle2 );
+
+ // Two siltons are in the same index bucket, so it won't increase the map size
+ assertEquals(2, map.size() );
+ assertEquals( 2, tablePopulationSize( map ) );
+
+ // cheddar is in its own buccket, which should be removed once empty. We cannot have
+ // empty FieldIndexEntries in the Map, as they get their value from the first FactEntry.
+ map.remove( cheddarHandle1 );
+ assertEquals( 1, map.size() );
+ assertEquals( 1, tablePopulationSize( map ) );
+
+ // We remove t he stiltonHandle2, but there is still one more stilton, so size should be the same
+ map.remove( stiltonHandle2 );
+ assertEquals( 1, map.size() );
+ assertEquals( 1, tablePopulationSize( map ) );
+
+ // No more stiltons, so the table should be empty
+ map.remove( stiltonHandle1 );
+ assertEquals( 0, map.size() );
+ assertEquals( 0, tablePopulationSize( map ) );
+ }
+
+ public void testResize() throws Exception {
+ // use this to access the map table
+ Field field = AbstractHashTable.class.getDeclaredField( "table" );
+ field.setAccessible( true );
+
+ // This should only resize when we have more than X different types of cheeses, not before.
+ ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
+
+ FieldIndexHashTable map = new FieldIndexHashTable( extractor.getIndex(), extractor );
+
+ assertEquals(0, map.size() );
+
+ Cheese stilton1 = new Cheese("stilton", 35);
+ map.add( new DefaultFactHandle( 1, stilton1 ) );
+
+ Cheese stilton2 = new Cheese("stilton", 81);
+ map.add( new DefaultFactHandle( 2, stilton2 ) );
+
+ Cheese cheddar1 = new Cheese("cheddar", 35);
+ map.add( new DefaultFactHandle( 3, cheddar1 ) );
+
+ Cheese cheddar2 = new Cheese("cheddar", 38);
+ map.add( new DefaultFactHandle( 4, cheddar2 ) );
+
+ Cheese brie = new Cheese("brie", 293);
+ map.add( new DefaultFactHandle( 5, brie ) );
+
+ Cheese mozerella = new Cheese("mozerella", 15);
+ map.add( new DefaultFactHandle( 6, mozerella ) );
+
+ Cheese dolcelatte = new Cheese("dolcelatte", 284);
+ map.add( new DefaultFactHandle( 7, dolcelatte ) );
+
+ Cheese camembert1 = new Cheese("camembert", 924);
+ map.add( new DefaultFactHandle( 8, camembert1 ) );
+
+ Cheese camembert2 = new Cheese("camembert", 765);
+ map.add( new DefaultFactHandle( 9, camembert2 ) );
+
+ Cheese redLeicestor = new Cheese("red leicestor", 23);
+ map.add( new DefaultFactHandle( 10, redLeicestor ) );
+
+ Cheese wensleydale = new Cheese("wensleydale", 20);
+ map.add( new DefaultFactHandle( 11, wensleydale ) );
+
+ Cheese edam = new Cheese("edam", 12);
+ map.add( new DefaultFactHandle( 12, edam ) );
+
+ Cheese goude1 = new Cheese("goude", 93);
+ map.add( new DefaultFactHandle( 13, goude1 ) );
+
+ Cheese goude2 = new Cheese("goude", 88);
+ map.add( new DefaultFactHandle( 14, goude2 ) );
+
+ Cheese gruyere = new Cheese("gruyere", 82);
+ map.add( new DefaultFactHandle( 15, gruyere ) );
+
+ Cheese emmental = new Cheese("emmental", 98);
+ map.add( new DefaultFactHandle( 16, emmental ) );
+
+ // At this point we have 16 facts but only 12 different types of cheeses
+ // so no table resize and thus its size is 16
+
+ assertEquals( 12, map.size() );
+
+ Entry[] table = (Entry[]) field.get( map );
+ assertEquals( 16, table.length);
+
+ Cheese feta = new Cheese("feta", 48);
+ map.add( new DefaultFactHandle( 2, feta ) );
+
+ // This adds our 13th type of cheese. The map is set with an initial capacity of 16 and
+ // a threshold of 75%, that after 12 it should resize the map to 32.
+ assertEquals( 13, map.size() );
+
+ table = (Entry[]) field.get( map );
+ assertEquals( 32, table.length);
+
+ Cheese haloumi = new Cheese("haloumi", 48);
+ map.add( new DefaultFactHandle( 2, haloumi ) );
+
+ Cheese chevre = new Cheese("chevre", 48);
+ map.add( new DefaultFactHandle( 2, chevre ) );
+
+ }
+
+ public static class TestClass {
+ private int hashCode;
+ private Object object;
+
+ public TestClass(){
+
+ }
+
+ public TestClass(int hashCode,
+ Object object) {
+ this.hashCode = hashCode;
+ this.object = object;
+ }
+
+ public Object getObject() {
+ return this.object;
+ }
+ public void setObject(Object object) {
+ this.object = object;
+ }
+ public void setHashCode(int hashCode) {
+ this.hashCode = hashCode;
+ }
+ public int hashCode() {
+ return this.hashCode;
+ }
+ public boolean equals(Object obj) {
+ if ( this == obj ) return true;
+ if ( obj == null ) return false;
+ if ( getClass() != obj.getClass() ) return false;
+ final TestClass other = (TestClass) obj;
+
+ if ( this.object == null ) {
+ if ( other.object != null ) return false;
+ } else if ( !this.object.equals( other.object ) ) return false;
+ return true;
+ }
+ }
+
+ private int tablePopulationSize(AbstractHashTable map) throws Exception {
+ Field field = AbstractHashTable.class.getDeclaredField( "table" );
+ field.setAccessible( true );
+ Entry[] array = (Entry[]) field.get( map );
+ int size = 0;
+ for ( int i = 0, length = array.length; i < length; i++ ) {
+ if ( array[i] != null ) {
+ size++;
+ }
+ }
+ return size;
+ }
+
+ private Entry[] getEntries(AbstractHashTable map) throws Exception {
+ Field field = AbstractHashTable.class.getDeclaredField( "table" );
+ field.setAccessible( true );
+ List list = new ArrayList();
+
+ Entry[] array = (Entry[]) field.get( map );
+ for ( int i = 0, length = array.length; i < length; i++ ) {
+ if ( array[i] != null ) {
+ list.add( array[i]);
+ }
+ }
+ return ( Entry[] ) list.toArray( new Entry[ list.size() ] );
+ }
+
+}
Deleted: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/FieldIndexMapTest.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -1,313 +0,0 @@
-package org.drools.util;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.drools.Cheese;
-import org.drools.base.ClassFieldExtractor;
-import org.drools.common.DefaultFactHandle;
-import org.drools.common.InternalFactHandle;
-
-public class FieldIndexMapTest extends TestCase {
-
- public void testSingleEntry() throws Exception {
- ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- assertEquals(0, map.size() );
-
- assertNull( map.get( "cheddar" ) );
-
- Cheese stilton1 = new Cheese("stilton", 35);
- InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
- map.add( stiltonHandle1 );
-
- assertEquals(1, map.size() );
- assertEquals( 1, tablePopulationSize( map ) );
-
- FieldIndexEntry stiltonEntry = map.get( "stilton" );
- assertSame( stiltonHandle1, stiltonEntry.getFirst().getFactHandle() );
- assertNull( stiltonEntry.getFirst().getNext() );
- }
-
- public void testTwoDifferentEntries() throws Exception {
- ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- assertEquals(0, map.size() );
-
- Cheese stilton1 = new Cheese("stilton", 35);
- InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
- map.add( stiltonHandle1 );
-
- Cheese cheddar1 = new Cheese("cheddar", 35);
- InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
- map.add( cheddarHandle1 );
-
- assertEquals(2, map.size() );
- assertEquals( 2, tablePopulationSize( map ) );
-
- FieldIndexEntry stiltonEntry = map.get( "stilton" );
- assertSame( stiltonHandle1, stiltonEntry.getFirst().getFactHandle() );
- assertNull( stiltonEntry.getFirst().getNext() );
-
- FieldIndexEntry cheddarEntry = map.get( "cheddar" );
- assertSame( cheddarHandle1, cheddarEntry.getFirst().getFactHandle() );
- assertNull( cheddarEntry.getFirst().getNext() );
- }
-
- public void testTwoEqualEntries() throws Exception {
- ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- assertEquals(0, map.size() );
-
- Cheese stilton1 = new Cheese("stilton", 35);
- InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
- map.add( stiltonHandle1 );
-
- Cheese cheddar1 = new Cheese("cheddar", 35);
- InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
- map.add( cheddarHandle1 );
-
- Cheese stilton2 = new Cheese("stilton", 81);
- InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3, stilton2 );
- map.add( stiltonHandle2 );
-
- // Two siltons are in the same index bucket, so it won't increase the map size
- assertEquals(2, map.size() );
- assertEquals( 2, tablePopulationSize( map ) );
-
- // Check they are correctly chained to the same FieldIndexEntry
- FieldIndexEntry stiltonEntry = map.get( "stilton" );
- assertSame( stiltonHandle2, stiltonEntry.getFirst().getFactHandle() );
- assertSame( stiltonHandle1, ((FactEntry)stiltonEntry.getFirst().getNext()).getFactHandle() );
- }
-
- public void testTwoDifferentEntriesSameHashCode() throws Exception {
- ClassFieldExtractor extractor = new ClassFieldExtractor(TestClass.class, "object");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- TestClass c1 = new TestClass( 0, new TestClass( 20, "stilton" ) );
- InternalFactHandle ch1 = new DefaultFactHandle( 1, c1 );
-
- map.add( ch1 );
-
- TestClass c2 = new TestClass( 0, new TestClass( 20, "cheddar" ) );
- InternalFactHandle ch2 = new DefaultFactHandle( 2, c2 );
- map.add( ch2 );
-
- // same hashcode, but different values, so it should result in a size of 2
- assertEquals(2, map.size() );
-
- // however both are in the same table bucket
- assertEquals( 1, tablePopulationSize( map ) );
-
-
- // this table bucket will have two FieldIndexEntries, as they are actually two different values
- FieldIndexEntry entry = (FieldIndexEntry) getEntries( map )[0];
-
- assertEquals( c2.getObject(), entry.getValue());
- assertEquals( c1.getObject(), ((FieldIndexEntry) entry.getNext()).getValue());
- }
-
- public void testRemove() throws Exception {
- ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- assertEquals(0, map.size() );
-
- Cheese stilton1 = new Cheese("stilton", 35);
- InternalFactHandle stiltonHandle1 = new DefaultFactHandle( 1, stilton1 );
- map.add( stiltonHandle1 );
-
- Cheese cheddar1 = new Cheese("cheddar", 35);
- InternalFactHandle cheddarHandle1 = new DefaultFactHandle( 2, cheddar1 );
- map.add( cheddarHandle1 );
-
- Cheese stilton2 = new Cheese("stilton", 81);
- InternalFactHandle stiltonHandle2 = new DefaultFactHandle( 3, stilton2 );
- map.add( stiltonHandle2 );
-
- // Two siltons are in the same index bucket, so it won't increase the map size
- assertEquals(2, map.size() );
- assertEquals( 2, tablePopulationSize( map ) );
-
- // cheddar is in its own buccket, which should be removed once empty. We cannot have
- // empty FieldIndexEntries in the Map, as they get their value from the first FactEntry.
- map.remove( cheddarHandle1 );
- assertEquals( 1, map.size() );
- assertEquals( 1, tablePopulationSize( map ) );
-
- // We remove t he stiltonHandle2, but there is still one more stilton, so size should be the same
- map.remove( stiltonHandle2 );
- assertEquals( 1, map.size() );
- assertEquals( 1, tablePopulationSize( map ) );
-
- // No more stiltons, so the table should be empty
- map.remove( stiltonHandle1 );
- assertEquals( 0, map.size() );
- assertEquals( 0, tablePopulationSize( map ) );
- }
-
- public void testResize() throws Exception {
- // use this to access the map table
- Field field = DroolsMap.class.getDeclaredField( "table" );
- field.setAccessible( true );
-
- // This should only resize when we have more than X different types of cheeses, not before.
- ClassFieldExtractor extractor = new ClassFieldExtractor(Cheese.class, "type");
-
- FieldIndexMap map = new FieldIndexMap( extractor.getIndex(), extractor );
-
- assertEquals(0, map.size() );
-
- Cheese stilton1 = new Cheese("stilton", 35);
- map.add( new DefaultFactHandle( 1, stilton1 ) );
-
- Cheese stilton2 = new Cheese("stilton", 81);
- map.add( new DefaultFactHandle( 2, stilton2 ) );
-
- Cheese cheddar1 = new Cheese("cheddar", 35);
- map.add( new DefaultFactHandle( 3, cheddar1 ) );
-
- Cheese cheddar2 = new Cheese("cheddar", 38);
- map.add( new DefaultFactHandle( 4, cheddar2 ) );
-
- Cheese brie = new Cheese("brie", 293);
- map.add( new DefaultFactHandle( 5, brie ) );
-
- Cheese mozerella = new Cheese("mozerella", 15);
- map.add( new DefaultFactHandle( 6, mozerella ) );
-
- Cheese dolcelatte = new Cheese("dolcelatte", 284);
- map.add( new DefaultFactHandle( 7, dolcelatte ) );
-
- Cheese camembert1 = new Cheese("camembert", 924);
- map.add( new DefaultFactHandle( 8, camembert1 ) );
-
- Cheese camembert2 = new Cheese("camembert", 765);
- map.add( new DefaultFactHandle( 9, camembert2 ) );
-
- Cheese redLeicestor = new Cheese("red leicestor", 23);
- map.add( new DefaultFactHandle( 10, redLeicestor ) );
-
- Cheese wensleydale = new Cheese("wensleydale", 20);
- map.add( new DefaultFactHandle( 11, wensleydale ) );
-
- Cheese edam = new Cheese("edam", 12);
- map.add( new DefaultFactHandle( 12, edam ) );
-
- Cheese goude1 = new Cheese("goude", 93);
- map.add( new DefaultFactHandle( 13, goude1 ) );
-
- Cheese goude2 = new Cheese("goude", 88);
- map.add( new DefaultFactHandle( 14, goude2 ) );
-
- Cheese gruyere = new Cheese("gruyere", 82);
- map.add( new DefaultFactHandle( 15, gruyere ) );
-
- Cheese emmental = new Cheese("emmental", 98);
- map.add( new DefaultFactHandle( 16, emmental ) );
-
- // At this point we have 16 facts but only 12 different types of cheeses
- // so no table resize and thus its size is 16
-
- assertEquals( 12, map.size() );
-
- Entry[] table = (Entry[]) field.get( map );
- assertEquals( 16, table.length);
-
- Cheese feta = new Cheese("feta", 48);
- map.add( new DefaultFactHandle( 2, feta ) );
-
- // This adds our 13th type of cheese. The map is set with an initial capacity of 16 and
- // a threshold of 75%, that after 12 it should resize the map to 32.
- assertEquals( 13, map.size() );
-
- table = (Entry[]) field.get( map );
- assertEquals( 32, table.length);
-
- Cheese haloumi = new Cheese("haloumi", 48);
- map.add( new DefaultFactHandle( 2, haloumi ) );
-
- Cheese chevre = new Cheese("chevre", 48);
- map.add( new DefaultFactHandle( 2, chevre ) );
-
- }
-
- public static class TestClass {
- private int hashCode;
- private Object object;
-
- public TestClass(){
-
- }
-
- public TestClass(int hashCode,
- Object object) {
- this.hashCode = hashCode;
- this.object = object;
- }
-
- public Object getObject() {
- return this.object;
- }
- public void setObject(Object object) {
- this.object = object;
- }
- public void setHashCode(int hashCode) {
- this.hashCode = hashCode;
- }
- public int hashCode() {
- return this.hashCode;
- }
- public boolean equals(Object obj) {
- if ( this == obj ) return true;
- if ( obj == null ) return false;
- if ( getClass() != obj.getClass() ) return false;
- final TestClass other = (TestClass) obj;
-
- if ( this.object == null ) {
- if ( other.object != null ) return false;
- } else if ( !this.object.equals( other.object ) ) return false;
- return true;
- }
- }
-
- private int tablePopulationSize(DroolsMap map) throws Exception {
- Field field = DroolsMap.class.getDeclaredField( "table" );
- field.setAccessible( true );
- Entry[] array = (Entry[]) field.get( map );
- int size = 0;
- for ( int i = 0, length = array.length; i < length; i++ ) {
- if ( array[i] != null ) {
- size++;
- }
- }
- return size;
- }
-
- private Entry[] getEntries(DroolsMap map) throws Exception {
- Field field = DroolsMap.class.getDeclaredField( "table" );
- field.setAccessible( true );
- List list = new ArrayList();
-
- Entry[] array = (Entry[]) field.get( map );
- for ( int i = 0, length = array.length; i < length; i++ ) {
- if ( array[i] != null ) {
- list.add( array[i]);
- }
- }
- return ( Entry[] ) list.toArray( new Entry[ list.size() ] );
- }
-
-}
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/ObjectHashMapTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/ObjectHashMapTest.java 2006-09-18 20:30:21 UTC (rev 6287)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/util/ObjectHashMapTest.java 2006-09-18 22:20:26 UTC (rev 6288)
@@ -0,0 +1,80 @@
+package org.drools.util;
+
+import junit.framework.TestCase;
+
+import org.drools.Cheese;
+
+public class ObjectHashMapTest extends TestCase {
+ public void testChechExistsFalse() {
+ ObjectHashMap map = new ObjectHashMap();
+ Cheese stilton = new Cheese("stilton", 5);
+ map.put(new Integer(1), stilton);
+
+ Cheese c = (Cheese) map.get(new Integer(1));
+ assertSame(stilton, c);
+
+ // we haven't told the map to check if the key exists, so we should end up with two entries.
+ // the second one is nolonger reacheable
+ Cheese cheddar = new Cheese("cheddar", 5);
+ map.put(new Integer(1), cheddar);
+ c = (Cheese) map.get(new Integer(1));
+ assertSame(cheddar, c);
+
+ Entry entry = map.getBucket( new Integer(1).hashCode() );
+ int size = 0;
+ while ( entry != null ) {
+ size++;
+ entry = entry.getNext();
+ }
+
+ assertEquals( 2, size);
+
+ // Check remove works, should leave one unreachable key
+ map.remove( new Integer(1) );
+ entry = map.getBucket( new Integer(1).hashCode() );
+ size = 0;
+ while ( entry != null ) {
+ size++;
+ entry = entry.getNext();
+ }
+
+ assertEquals( 1, size);
+ }
+
+ public void testChechExistsTrue() {
+ ObjectHashMap map = new ObjectHashMap();
+ map.setCheckExists( true );
+ Cheese stilton = new Cheese("stilton", 5);
+ map.put(new Integer(1), stilton);
+
+ Cheese c = (Cheese) map.get(new Integer(1));
+ assertSame(stilton, c);
+
+ // we haven't told the map to check if the key exists, so we should end up with two entries.
+ // the second one is nolonger reacheable
+ Cheese cheddar = new Cheese("cheddar", 5);
+ map.put(new Integer(1), cheddar);
+ c = (Cheese) map.get(new Integer(1));
+ assertSame(cheddar, c);
+
+ Entry entry = map.getBucket( new Integer(1).hashCode() );
+ int size = 0;
+ while ( entry != null ) {
+ size++;
+ entry = entry.getNext();
+ }
+
+ assertEquals( 1, size);
+
+ // Check remove works
+ map.remove( new Integer(1) );
+ entry = map.getBucket( new Integer(1).hashCode() );
+ size = 0;
+ while ( entry != null ) {
+ size++;
+ entry = entry.getNext();
+ }
+
+ assertEquals( 0, size);
+ }
+}
More information about the jboss-svn-commits
mailing list