[jboss-svn-commits] JBL Code SVN: r14396 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/reteoo and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Aug 20 20:51:41 EDT 2007
Author: mark.proctor at jboss.com
Date: 2007-08-20 20:51:41 -0400 (Mon, 20 Aug 2007)
New Revision: 14396
Added:
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.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/FactHandleIndexHashTable.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java
Log:
JBRULES-1102 Bug in DefaultBetaConstraint class indexing to never turn on
-Fixed DefaultBetaConstraints
-Added comprehensive unit test
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 2007-08-20 23:36:02 UTC (rev 14395)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultBetaConstraints.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -72,7 +72,7 @@
// First create a LinkedList of constraints, with the indexed constraints first.
for ( int i = 0, length = constraints.length; i < length; i++ ) {
// Determine if this constraint is indexable
- if ( (!disableIndexing) && conf.isIndexLeftBetaMemory() && conf.isIndexRightBetaMemory() && isIndexable( constraints[i] ) && ( depth <= this.indexed ) ) {
+ if ( (!disableIndexing) && conf.isIndexLeftBetaMemory() && conf.isIndexRightBetaMemory() && isIndexable( constraints[i] ) && ( this.indexed < depth-1 ) ) {
if ( depth >= 1 && this.indexed == -1 ) {
// first index, so just add to the front
this.constraints.insertAfter( null,
@@ -189,8 +189,13 @@
}
public boolean isIndexed() {
- return this.indexed > 0;
+ // false if -1
+ return this.indexed >= 0;
}
+
+ public int getIndexCount() {
+ return this.indexed;
+ }
public boolean isEmpty() {
return false;
@@ -198,11 +203,11 @@
public BetaMemory createBetaMemory(RuleBaseConfiguration config) {
BetaMemory memory;
- if ( this.indexed > 0 ) {
+ if ( this.indexed >= 0 ) {
LinkedListEntry entry = (LinkedListEntry) this.constraints.getFirst();
final List list = new ArrayList();
- for ( int pos = 0; pos < this.indexed; pos++ ) {
+ for ( int pos = 0; pos <= this.indexed; pos++ ) {
final Constraint constraint = (Constraint) entry.getObject();
final VariableConstraint variableConstraint = (VariableConstraint) constraint;
final FieldIndex index = new FieldIndex( variableConstraint.getFieldExtractor(),
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java 2007-08-20 23:36:02 UTC (rev 14395)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -221,7 +221,7 @@
throw new RuntimeException( "Cannot have a stateful rule session, with sequential configuration set to true" );
}
ReteooStatefulSession session = null;
-
+
synchronized ( this.pkgs ) {
ExecutorService executor = this.config.getExecutorService();
session = new ReteooStatefulSession( nextWorkingMemoryCounter(),
@@ -237,10 +237,10 @@
final InitialFactHandle handle = new InitialFactHandle( session.getFactHandleFactory().newFactHandle( new InitialFactHandleDummyObject() ) );
session.queueWorkingMemoryAction( new WorkingMemoryReteAssertAction( handle,
- false,
- true,
- null,
- null ) );
+ false,
+ true,
+ null,
+ null ) );
}
return session;
}
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 2007-08-20 23:36:02 UTC (rev 14395)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/AbstractHashTable.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -434,7 +434,9 @@
}
}
- public static interface Index {
+ public static interface Index {
+ public FieldIndex getFieldIndex(int index);
+
public int hashCodeOf(ReteTuple tuple);
public int hashCodeOf(Object object);
@@ -466,9 +468,16 @@
this.extractor = indexes[0].extractor;
this.declaration = indexes[0].declaration;
this.evaluator = indexes[0].evaluator;
+ }
+ public FieldIndex getFieldIndex(int index) {
+ if ( index > 0 ) {
+ throw new IllegalArgumentException("Index position " + index + " does not exist" );
+ }
+ return new FieldIndex(extractor, declaration, evaluator);
}
-
+
+
public int hashCodeOf(final Object object) {
int hashCode = this.startResult;
hashCode = TupleIndexHashTable.PRIME * hashCode + this.extractor.getHashCode( null, object );
@@ -534,8 +543,18 @@
this.index0 = indexes[0];
this.index1 = indexes[1];
-
}
+
+ public FieldIndex getFieldIndex(int index) {
+ switch ( index ) {
+ case 0:
+ return index0;
+ case 1:
+ return index1;
+ default:
+ throw new IllegalArgumentException("Index position " + index + " does not exist" );
+ }
+ }
public int hashCodeOf(final Object object) {
int hashCode = this.startResult;
@@ -622,8 +641,20 @@
this.index0 = indexes[0];
this.index1 = indexes[1];
this.index2 = indexes[2];
-
}
+
+ public FieldIndex getFieldIndex(int index) {
+ switch ( index ) {
+ case 0:
+ return index0;
+ case 1:
+ return index1;
+ case 2:
+ return index2;
+ default:
+ throw new IllegalArgumentException("Index position " + index + " does not exist" );
+ }
+ }
public int hashCodeOf(final Object object) {
int hashCode = this.startResult;
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java 2007-08-20 23:36:02 UTC (rev 14395)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/FactHandleIndexHashTable.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -77,6 +77,10 @@
public boolean isIndexed() {
return true;
}
+
+ public Index getIndex() {
+ return this.index;
+ }
public Entry getBucket(final Object object) {
final int hashCode = this.index.hashCodeOf( object );
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java 2007-08-20 23:36:02 UTC (rev 14395)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/TupleIndexHashTable.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -81,6 +81,10 @@
public boolean isIndexed() {
return true;
}
+
+ public Index getIndex() {
+ return this.index;
+ }
public Entry getBucket(final Object object) {
final int hashCode = this.index.hashCodeOf( object );
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/DefaultBetaConstraintsTest.java 2007-08-21 00:51:41 UTC (rev 14396)
@@ -0,0 +1,249 @@
+package org.drools.common;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.Cheese;
+import org.drools.Person;
+import org.drools.RuleBaseConfiguration;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassFieldExtractorCache;
+import org.drools.base.ClassObjectType;
+import org.drools.base.FieldFactory;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.base.evaluators.StringFactory;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Pattern;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.util.FactHandleIndexHashTable;
+import org.drools.util.FactHashTable;
+import org.drools.util.TupleHashTable;
+import org.drools.util.TupleIndexHashTable;
+import org.drools.util.AbstractHashTable.DoubleCompositeIndex;
+import org.drools.util.AbstractHashTable.FieldIndex;
+import org.drools.util.AbstractHashTable.Index;
+import org.drools.util.AbstractHashTable.SingleIndex;
+import org.drools.util.AbstractHashTable.TripleCompositeIndex;
+
+import junit.framework.TestCase;
+
+public class DefaultBetaConstraintsTest extends TestCase {
+
+ public void testNoIndexConstraints() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint5 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3,constraint5 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint6 = ( VariableConstraint ) getConstraint( "cheeseType6", Operator.NOT_EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5, constraint6 };
+ checkBetaConstraints( constraints );
+ }
+
+ public void testIndexedConstraint() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType0", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint5 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5 };
+ checkBetaConstraints( constraints );
+
+ VariableConstraint constraint6 = ( VariableConstraint ) getConstraint( "cheeseType6", Operator.EQUAL, "type", Cheese.class );
+ constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4, constraint5, constraint6 };
+ checkBetaConstraints( constraints );
+ }
+
+
+ public void testSingleIndex() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+ checkBetaConstraints( constraints );
+ }
+
+ public void testSingleIndexNotFirst() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+
+ checkBetaConstraints( constraints );
+ }
+
+ public void testDoubleIndex() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.NOT_EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+
+ checkBetaConstraints( constraints );
+ }
+
+ public void testDoubleIndexNotFirst() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+
+ checkBetaConstraints( constraints );
+ }
+
+
+ public void testTripleIndex() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+
+ checkBetaConstraints( constraints );
+ }
+
+ public void testTripleIndexNotFirst() {
+ VariableConstraint constraint0 = ( VariableConstraint ) getConstraint( "cheeseType1", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint1 = ( VariableConstraint ) getConstraint( "cheeseType2", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint2 = ( VariableConstraint ) getConstraint( "cheeseType3", Operator.NOT_EQUAL, "type", Cheese.class );
+ VariableConstraint constraint3 = ( VariableConstraint ) getConstraint( "cheeseType4", Operator.EQUAL, "type", Cheese.class );
+ VariableConstraint constraint4 = ( VariableConstraint ) getConstraint( "cheeseType5", Operator.EQUAL, "type", Cheese.class );
+
+ VariableConstraint[] constraints = new VariableConstraint[] { constraint0, constraint1, constraint2, constraint3, constraint4 };
+
+ checkBetaConstraints( constraints );
+ }
+
+ private BetaNodeFieldConstraint getConstraint(String identifier,
+ Operator operator,
+ String fieldName,
+ Class clazz) {
+ FieldExtractor extractor = ClassFieldExtractorCache.getExtractor( clazz,
+ fieldName,
+ getClass().getClassLoader() );
+ Declaration declaration = new Declaration( identifier,
+ extractor,
+ new Pattern( 0,
+ new ClassObjectType( clazz ) ) );
+ Evaluator evaluator = StringFactory.getInstance().getEvaluator( operator );
+ return new VariableConstraint( extractor,
+ declaration,
+ evaluator );
+ }
+
+
+ private void checkBetaConstraints(VariableConstraint[] constraints) {
+ RuleBaseConfiguration config = new RuleBaseConfiguration();
+ int depth = config.getCompositeKeyDepth();
+
+ List list = new ArrayList();
+
+ // get indexed positions
+ for ( int i = 0; i < constraints.length && list.size() < depth; i++ ) {
+ if ( constraints[i].getEvaluator().getOperator() == Operator.EQUAL ) {
+ list.add( new Integer(i) );
+ }
+ }
+
+ // convert to array
+ int[] indexedPositions = new int[ list.size() ];
+ for ( int i = 0; i < list.size(); i++ ) {
+ indexedPositions[i] = ( (Integer)list.get( i ) ).intValue();
+ }
+
+ DefaultBetaConstraints betaConstraints = new DefaultBetaConstraints(constraints, config );
+
+ assertEquals( ( indexedPositions.length > 0 ), betaConstraints.isIndexed() );
+ assertEquals(indexedPositions.length-1, betaConstraints.getIndexCount() );
+ BetaMemory betaMemory = betaConstraints.createBetaMemory( config );
+
+ // test tuple side
+ if ( indexedPositions.length > 0 ) {
+ TupleIndexHashTable tupleHashTable = ( TupleIndexHashTable ) betaMemory.getTupleMemory();
+ assertTrue( tupleHashTable.isIndexed() );
+ Index index = tupleHashTable.getIndex();
+
+ for ( int i = 0; i < indexedPositions.length; i++ ) {
+ checkSameConstraintForIndex( constraints[indexedPositions[i]], index.getFieldIndex(i) );
+ }
+
+ FactHandleIndexHashTable factHashTable = ( FactHandleIndexHashTable ) betaMemory.getFactHandleMemory();
+ assertTrue( factHashTable.isIndexed() );
+ index = factHashTable.getIndex();
+
+ for ( int i = 0; i < indexedPositions.length; i++ ) {
+ checkSameConstraintForIndex( constraints[indexedPositions[i]], index.getFieldIndex(i) );
+ }
+ } else {
+ TupleHashTable tupleHashTable = ( TupleHashTable ) betaMemory.getTupleMemory();
+ assertFalse( tupleHashTable.isIndexed() );
+
+ FactHashTable factHashTable = ( FactHashTable ) betaMemory.getFactHandleMemory();
+ assertFalse( factHashTable.isIndexed() );
+ }
+ }
+
+
+ private void checkSameConstraintForIndex(VariableConstraint constraint, FieldIndex fieldIndex) {
+ assertSame( constraint.getRequiredDeclarations()[0], fieldIndex.getDeclaration() );
+ assertSame( constraint.getEvaluator(), fieldIndex.getEvaluator() );
+ assertSame( constraint.getFieldExtractor(), fieldIndex.getExtractor() );
+ }
+}
More information about the jboss-svn-commits
mailing list