[jboss-svn-commits] JBL Code SVN: r5945 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/leaps main/java/org/drools/leaps/util test/java/org/drools/leaps
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sat Aug 19 01:27:47 EDT 2006
Author: bagerman
Date: 2006-08-19 01:27:40 -0400 (Sat, 19 Aug 2006)
New Revision: 5945
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java
Log:
>From constraint
Deftemplate
Hashing table now used for Not and Exists table scans
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -20,7 +20,6 @@
import java.util.List;
import org.drools.WorkingMemory;
-import org.drools.base.ClassObjectType;
import org.drools.common.BetaNodeBinder;
import org.drools.common.InternalFactHandle;
import org.drools.rule.Column;
@@ -34,7 +33,7 @@
*
*/
public class ColumnConstraints implements Serializable {
- private Class classType;
+ private Object classType;
private final FieldConstraint[] alphaConstraints;
@@ -47,7 +46,7 @@
public ColumnConstraints(final Column column,
final List alpha,
final BetaNodeBinder beta) {
- this.classType = ((ClassObjectType) column.getObjectType()).getClassType();
+ this.classType = LeapsBuilder.getLeapsClassType( column.getObjectType() );
if ( beta != null ) {
this.beta = beta;
@@ -65,7 +64,7 @@
}
}
- protected final Class getClassType() {
+ protected final Object getClassType() {
return this.classType;
}
@@ -111,5 +110,12 @@
protected final boolean isAlphaPresent() {
return this.alphaPresent;
}
-
+
+ protected FieldConstraint[] getAlphaContraints() {
+ return this.alphaConstraints;
+ }
+
+ protected FieldConstraint[] getBetaContraints() {
+ return this.beta.getConstraints( );
+ }
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -16,13 +16,17 @@
* limitations under the License.
*/
+import java.util.Comparator;
import java.util.Iterator;
-import java.util.LinkedList;
import org.drools.common.DefaultFactHandle;
import org.drools.common.PropagationContextImpl;
+import org.drools.leaps.util.IteratorFromPositionToTableStart;
import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.IdentityMap;
/**
* Implementation of a container to store data elements used throughout the
@@ -53,7 +57,7 @@
* Tuples that are either already on agenda or are very close (missing
* exists or have not facts matching)
*/
- private LinkedList tuples;
+ private final IdentityMap tuples;
/**
* initializes base LeapsTable with appropriate Comparator and positive and
@@ -65,7 +69,9 @@
public FactTable(final ConflictResolver conflictResolver) {
super( conflictResolver.getFactConflictResolver( ) );
this.rules = new RuleTable( conflictResolver.getRuleConflictResolver( ) );
- this.tuples = new LinkedList( );
+ this.tuples = new IdentityMap();
+ this.comparator = conflictResolver.getFactConflictResolver( );
+ this.notAndExistsHashedTables = new IdentityMap( );
}
/**
@@ -92,15 +98,12 @@
final LeapsRuleHandle ruleHandle ) {
this.rules.remove( ruleHandle );
// remove tuples that are still there
- final LinkedList list = new LinkedList( );
-
for (final Iterator it = this.getTuplesIterator( ); it.hasNext( );) {
final LeapsTuple tuple = (LeapsTuple) it.next( );
- if (ruleHandle.getLeapsRule( ).getRule( ) != tuple.getLeapsRule( ).getRule( )) {
- list.add( tuple );
+ if (ruleHandle.getLeapsRule( ).getRule( ) == tuple.getLeapsRule( ).getRule( )) {
+ this.tuples.remove( tuple );
}
}
- this.tuples = list;
}
/**
@@ -167,7 +170,7 @@
ret.append( "\nTuples :" );
- for (final Iterator it = this.tuples.iterator( ); it.hasNext( );) {
+ for (final Iterator it = this.tuples.values( ).iterator( ); it.hasNext( );) {
ret.append( "\n" + it.next( ) );
}
@@ -183,10 +186,74 @@
}
protected Iterator getTuplesIterator() {
- return this.tuples.iterator( );
+ return this.tuples.values( ).iterator( );
}
protected void addTuple( final LeapsTuple tuple ) {
- this.tuples.add( tuple );
+ this.tuples.put( tuple,tuple );
}
+
+ protected void removeTuple( final LeapsTuple tuple ) {
+ this.tuples.remove( tuple );
+ }
+
+
+ private final IdentityMap notAndExistsHashedTables;
+
+ private final Comparator comparator;
+
+ public void add( Object object ) {
+ super.add( object );
+ for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
+ ((HashedTableComponent)it.next( )).add( (LeapsFactHandle)object );
+ }
+ }
+
+ public void remove( Object object ) {
+ super.remove( object );
+ for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
+ ((HashedTableComponent)it.next( )).remove( (LeapsFactHandle)object );
+ }
+ }
+
+ protected void createHashedSubTable(ColumnConstraints constraint) {
+ this.notAndExistsHashedTables.put( constraint, new HashedTableComponent( constraint,
+ this.comparator ) );
+ }
+
+ protected TableIterator reverseOrderIterator( Tuple tuple, ColumnConstraints constraint ) {
+ TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).reverseOrderIterator( tuple );
+ if (ret == null){
+ ret = Table.emptyIterator( );
+ }
+ return ret;
+ }
+
+ protected TableIterator iteratorFromPositionToTableStart( Tuple tuple,
+ ColumnConstraints constraint,
+ LeapsFactHandle startFactHandle,
+ LeapsFactHandle currentFactHandle ) {
+ TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).iteratorFromPositionToTableStart( tuple,
+ startFactHandle,
+ currentFactHandle );
+ if (ret == null) {
+ ret = Table.emptyIterator( );
+ }
+ return ret;
+ }
+
+ protected TableIterator iteratorFromPositionToTableEnd( Tuple tuple,
+ ColumnConstraints constraint,
+ LeapsFactHandle startFactHandle ) {
+ TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).iteratorFromPositionToTableEnd( tuple,
+ startFactHandle );
+ if (ret == null) {
+ ret = Table.emptyIterator( );
+ }
+ return ret;
+ }
+
+ protected Iterator getHashedConstraints(){
+ return this.notAndExistsHashedTables.keySet( ).iterator( );
+ }
}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,25 @@
+package org.drools.leaps;
+
+import java.util.Arrays;
+
+import org.drools.common.BetaNodeBinder;
+import org.drools.rule.Column;
+import org.drools.spi.DataProvider;
+
+public class FromConstraint extends ColumnConstraints {
+ private final DataProvider provider;
+
+ public FromConstraint(Column column,
+ DataProvider provider,
+ ColumnConstraints constraints) {
+ super( column,
+ ( constraints.getAlphaContraints( ) == null || constraints.getAlphaContraints( ).length == 0 ) ? Arrays.asList( new FromConstraint[0] )
+ : Arrays.asList( constraints.getAlphaContraints( ) ),
+ new BetaNodeBinder( constraints.getBetaContraints( ) ) );
+ this.provider = provider;
+ }
+
+ public DataProvider getProvider() {
+ return provider;
+ }
+}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,162 @@
+package org.drools.leaps;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.base.evaluators.Operator;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.Declaration;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Tuple;
+
+public class HashedTableComponent implements Serializable{
+ private final ColumnConstraints constraints;
+
+ private final int numberOfVariableConstraints;
+
+ private final Map buckets;
+
+ private final Comparator comparator;
+
+ private final static Integer DEFAULT_HASH = new Integer( 0 );
+
+ private final Table noConstraintsTable;
+
+ public HashedTableComponent(ColumnConstraints constraints, Comparator comparator) {
+ this.constraints = constraints;
+ this.comparator = comparator;
+ this.buckets = new HashMap( );
+ this.numberOfVariableConstraints = this.constraints.getBetaContraints( ).length;
+ this.noConstraintsTable = new Table(this.comparator);
+ }
+
+ public void add( LeapsFactHandle factHandle ) {
+ Table table = this.getTable( factHandle, true );
+ if (table != null) {
+ table.add( factHandle );
+ }
+ }
+
+ public void remove( LeapsFactHandle factHandle ) {
+ Table table = this.getTable( factHandle, false );
+ if (table != null) {
+ table.remove( factHandle );
+ }
+ }
+
+ public TableIterator reverseOrderIterator( Tuple tuple ) {
+ Table table = this.getTable( tuple );
+ if (table != null) {
+ return table.reverseOrderIterator( );
+ }
+ else {
+ return null;
+ }
+ }
+
+ public TableIterator iteratorFromPositionToTableEnd( Tuple tuple,
+ LeapsFactHandle startFactHandle ) {
+ Table table = this.getTable( tuple );
+ if (table != null) {
+ return table.iteratorFromPositionToTableEnd( startFactHandle );
+ }
+ else {
+ return null;
+ }
+ }
+
+ public TableIterator iteratorFromPositionToTableStart( Tuple tuple,
+ LeapsFactHandle startFactHandle,
+ LeapsFactHandle currentFactHandle ) {
+ Table table = this.getTable( tuple );
+ if (table != null) {
+ return table.iteratorFromPositionToTableStart( startFactHandle,
+ currentFactHandle );
+ }
+ else {
+ return null;
+ }
+ }
+
+ private Table getTable( Tuple tuple ) {
+ Table ret = null;
+ if (this.numberOfVariableConstraints > 0) {
+ Map currentMap = this.buckets;
+ for (int i = 0; ( i < this.numberOfVariableConstraints )
+ && ( currentMap != null ); i++) {
+ Integer hash = DEFAULT_HASH;
+ if (this.constraints.getBetaContraints( )[i] instanceof VariableConstraint
+ && ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getEvaluator( )
+ .getOperator( ) == Operator.EQUAL) {
+ Declaration declaration = this.constraints.getBetaContraints( )[i].getRequiredDeclarations( )[0];
+ final Object select = declaration.getValue( tuple.get( declaration.getColumn( )
+ .getFactIndex( ) )
+ .getObject( ) );
+ if (select != null) {
+ hash = new Integer( select.hashCode( ) );
+ }
+ }
+ // put facts at the very bottom / last instance
+ if (i != ( this.numberOfVariableConstraints - 1 )) {
+ // we can not have null as a value to the key
+ currentMap = (Map) currentMap.get( hash );
+ }
+ else {
+ ret = (Table) currentMap.get( hash );
+ }
+ }
+ }
+ else {
+ ret = this.noConstraintsTable;
+ }
+ return ret;
+ }
+
+ private Table getTable( LeapsFactHandle factHandle, boolean createIfNotThere ) {
+ Table ret = null;
+ Map currentMap = this.buckets;
+ if (this.constraints.isAllowedAlpha( factHandle, null, null )) {
+ if (this.numberOfVariableConstraints > 0) {
+ for (int i = 0; ( i < this.numberOfVariableConstraints )
+ && ( currentMap != null ); i++) {
+ Integer hash = DEFAULT_HASH;
+ if (this.constraints.getBetaContraints( )[i] instanceof VariableConstraint
+ && ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getEvaluator( )
+ .getOperator( ) == Operator.EQUAL) {
+ final Object select = ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getFieldExtractor( )
+ .getValue( factHandle.getObject( ) );
+ if (select != null) {
+ hash = new Integer( select.hashCode( ) );
+ }
+ }
+ // put facts at the very bottom / last instance
+ if (i != ( this.numberOfVariableConstraints - 1 )) {
+ // we can not have null as a value to the key
+ Map map = (Map) currentMap.get( hash );
+ if (map == null && createIfNotThere) {
+ map = new HashMap( );
+ currentMap.put( hash, map );
+ }
+ currentMap = map;
+ }
+ else {
+ Table table = (Table) currentMap.get( hash );
+ if (table == null && createIfNotThere) {
+ table = new Table( this.comparator );
+ currentMap.put( hash, table );
+ }
+ ret = table;
+ }
+ }
+ }
+ else {
+ return this.noConstraintsTable;
+ }
+ }
+ return ret;
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -55,6 +55,7 @@
.isEmpty( ) )) {
// fire regular rule
super.fireActivation( activation );
+ ((LeapsTuple)activation.getTuple( )).setWasFired( true );
if (activation.getRule( ).getActivationGroup( ) != null) {
this.getActivationGroup( activation.getRule( ).getActivationGroup( ) );
}
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,259 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.base.ClassObjectType;
+import org.drools.common.BetaNodeBinder;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.rule.And;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Exists;
+import org.drools.rule.From;
+import org.drools.rule.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Not;
+import org.drools.rule.Rule;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.ObjectType;
+
+/**
+ * A Rule<code>Builder</code> to process <code>Rule</code>s for use with
+ * Leaps WorkingMemories. Produces list of Leaps rules that wrap Rule and can be
+ * used in Leaps algorithm. All methods are static
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class LeapsBuilder {
+ /**
+ * follows RETEOO logic flow but returns leaps rules list
+ *
+ * @param rule
+ * @return list of leaps rule
+ * @throws InvalidPatternException
+ */
+ final protected static List processRule(final Rule rule) throws InvalidPatternException {
+ final ArrayList leapsRules = new ArrayList();
+ final And[] and = rule.getTransformedLhs();
+ for ( int i = 0, length = and.length; i < length; i++ ) {
+ leapsRules.addAll( processRuleForAnd( and[i],
+ rule ) );
+ }
+ return leapsRules;
+ }
+
+ /**
+ * Creates list of leaps rules for each individual And
+ *
+ * @param and
+ * @param rule
+ * @return list of leaps rules for the given And
+ */
+ final private static List processRuleForAnd(final And and,
+ final Rule rule) {
+ ColumnConstraints constraints;
+ final ArrayList leapsRules = new ArrayList();
+ final ArrayList cols = new ArrayList();
+ final ArrayList notCols = new ArrayList();
+ final ArrayList existsCols = new ArrayList();
+ final ArrayList evalConditions = new ArrayList();
+ for ( final Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
+ final Object object = it.next();
+ if ( object instanceof EvalCondition ) {
+ final EvalCondition eval = (EvalCondition) object;
+ evalConditions.add( eval );
+ } else {
+ if ( object instanceof Column ) {
+ constraints = LeapsBuilder.processColumn( (Column) object );
+ // create column constraints
+ } else if ( object instanceof From ){
+ constraints = LeapsBuilder.processColumn( ((From) object).getColumn( ) );
+ }
+ else {
+ // NOTS and EXISTS
+ GroupElement ce = (GroupElement) object;
+ while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
+ ce = (GroupElement) ce.getChildren().get( 0 );
+ }
+ constraints = LeapsBuilder.processColumn( (Column) ce.getChildren().get( 0 ) );
+ }
+ if (object.getClass( ) == Not.class) {
+ notCols.add( constraints );
+ }
+ else if (object.getClass( ) == Exists.class) {
+ existsCols.add( constraints );
+ }
+ else if (object.getClass( ) == From.class) {
+ cols.add( new FromConstraint(((From)object).getColumn( ), ((From)object).getDataProvider( ), constraints ));
+ }
+ else {
+ cols.add( constraints );
+ }
+ }
+ }
+
+ // check eval for presence of required declarations
+ checkEvalUnboundDeclarations( rule,
+ evalConditions );
+ //
+ leapsRules.add( new LeapsRule( rule,
+ cols,
+ notCols,
+ existsCols,
+ evalConditions) );
+
+ return leapsRules;
+ }
+
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ static void checkEvalUnboundDeclarations(final Rule rule,
+ final ArrayList evals) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( final Iterator it = evals.iterator(); it.hasNext(); ) {
+ final EvalCondition ec = (EvalCondition) it.next();
+ final Declaration[] declarations = ec.getRequiredDeclarations();
+ for ( int i = 0, length = declarations.length; i < length; i++ ) {
+ if ( rule.getDeclaration( declarations[i].getIdentifier() ) == null ) {
+ list.add( declarations[i].getIdentifier() );
+ }
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+ }
+
+ /**
+ * extracts column specific constraints and packages it into
+ * <code>ColumnConstraints</code>
+ *
+ * @param column
+ * @param and
+ * @return leaps packaged ColumnConstraints
+ */
+ final private static ColumnConstraints processColumn(final Column column ) {
+ BetaNodeBinder binder;
+ final List alphaConstraints = new ArrayList( );
+ final List predicateConstraints = new ArrayList( );
+
+ final List constraints = column.getConstraints( );
+
+ Map declarations = new HashMap( );
+
+ if (column.getDeclaration( ) != null) {
+ final Declaration declaration = column.getDeclaration( );
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier( ), declaration );
+ }
+
+ for (final Iterator it = constraints.iterator( ); it.hasNext( );) {
+ final Object object = it.next( );
+ // Check if its a declaration
+ if (object instanceof Declaration) {
+ final Declaration declaration = (Declaration) object;
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier( ), declaration );
+ continue;
+ }
+
+ final FieldConstraint fieldConstraint = (FieldConstraint) object;
+ if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+ alphaConstraints.add( fieldConstraint);
+ } else {
+ predicateConstraints.add( fieldConstraint );
+ }
+ }
+
+ if ( !predicateConstraints.isEmpty() ) {
+ binder = new BetaNodeBinder( (FieldConstraint[]) predicateConstraints.toArray( new FieldConstraint[predicateConstraints.size()] ) );
+ } else {
+ binder = new BetaNodeBinder();
+ }
+
+ return new ColumnConstraints( column,
+ alphaConstraints,
+ binder );
+ }
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ private static void checkUnboundDeclarations(final Map declarations, final Declaration[] requiredDeclarations) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( int i = 0, length = requiredDeclarations.length; i < length; i++ ) {
+ if ( declarations.get( requiredDeclarations[i].getIdentifier() ) == null ) {
+ list.add( requiredDeclarations[i].getIdentifier() );
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+
+ }
+
+ public static Object getLeapsClassType(Object o) {
+ if(o instanceof org.drools.facttemplates.Fact) {
+ return ((org.drools.facttemplates.Fact)o).getFactTemplate( ).getName( );
+ }
+ else {
+ return o.getClass( );
+ }
+ }
+
+ public static Object getLeapsClassType(ObjectType ot) {
+ if(ot.getClass( ) == FactTemplateObjectType.class) {
+ return ((FactTemplateObjectType) ot).getFactTemplate( ).getName( );
+ }
+ else {
+ // we assume that it's classobject type
+ return ((ClassObjectType) ot).getClassType();
+ }
+ }
+
+}
\ No newline at end of file
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -50,28 +50,28 @@
final Class[] existsNotsClasses;
public LeapsRule(final Rule rule,
- final ArrayList columns,
- final ArrayList notColumns,
- final ArrayList existsColumns,
- final ArrayList evalConditions) {
+ final ArrayList columns,
+ final ArrayList notColumns,
+ final ArrayList existsColumns,
+ final ArrayList evalConditions) {
this.rule = rule;
this.columnConstraints = (ColumnConstraints[]) columns.toArray( new ColumnConstraints[0] );
this.notColumnConstraints = (ColumnConstraints[]) notColumns.toArray( new ColumnConstraints[0] );
this.existsColumnConstraints = (ColumnConstraints[]) existsColumns.toArray( new ColumnConstraints[0] );
this.evalConditions = (EvalCondition[]) evalConditions.toArray( new EvalCondition[0] );
- this.notColumnsPresent = (this.notColumnConstraints.length != 0);
- this.existsColumnsPresent = (this.existsColumnConstraints.length != 0);
- this.evalCoditionsPresent = (this.evalConditions.length != 0);
+ this.notColumnsPresent = ( this.notColumnConstraints.length != 0 );
+ this.existsColumnsPresent = ( this.existsColumnConstraints.length != 0 );
+ this.evalCoditionsPresent = ( this.evalConditions.length != 0 );
- final ArrayList classes = new ArrayList();
- for ( int i = 0; i < this.notColumnConstraints.length; i++ ) {
- if ( !classes.contains( this.notColumnConstraints[i].getClassType() ) ) {
- classes.add( this.notColumnConstraints[i].getClassType() );
+ final ArrayList classes = new ArrayList( );
+ for (int i = 0; i < this.notColumnConstraints.length; i++) {
+ if (!classes.contains( this.notColumnConstraints[i].getClassType( ) )) {
+ classes.add( this.notColumnConstraints[i].getClassType( ) );
}
}
- for ( int i = 0; i < this.existsColumnConstraints.length; i++ ) {
- if ( !classes.contains( this.existsColumnConstraints[i].getClassType() ) ) {
- classes.add( this.existsColumnConstraints[i].getClassType() );
+ for (int i = 0; i < this.existsColumnConstraints.length; i++) {
+ if (!classes.contains( this.existsColumnConstraints[i].getClassType( ) )) {
+ classes.add( this.existsColumnConstraints[i].getClassType( ) );
}
}
@@ -98,11 +98,11 @@
return this.evalConditions.length;
}
- Class getColumnClassObjectTypeAtPosition(final int idx) {
- return this.columnConstraints[idx].getClassType();
+ Object getColumnClassObjectTypeAtPosition( final int idx ) {
+ return this.columnConstraints[idx].getClassType( );
}
- ColumnConstraints getColumnConstraintsAtPosition(final int idx) {
+ ColumnConstraints getColumnConstraintsAtPosition( final int idx ) {
return this.columnConstraints[idx];
}
@@ -131,10 +131,10 @@
}
public int hashCode() {
- return this.rule.hashCode();
+ return this.rule.hashCode( );
}
- public boolean equals(final Object that) {
+ public boolean equals( final Object that ) {
return this == that;
}
@@ -153,7 +153,7 @@
return this.agendaGroup;
}
- public void setAgendaGroup(final AgendaGroupImpl agendaGroup) {
+ public void setAgendaGroup( final AgendaGroupImpl agendaGroup ) {
this.agendaGroup = agendaGroup;
}
-}
\ No newline at end of file
+}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -127,7 +127,7 @@
InvalidPatternException {
super.addRule( rule );
- final List rules = Builder.processRule( rule );
+ final List rules = LeapsBuilder.processRule( rule );
this.leapsRules.put( rule,
rules );
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -48,8 +48,9 @@
private Activation activation;
- private final LeapsRule leapsRule;
+ private final LeapsRule leapsRule;
+ private boolean wasFired = false;
/**
* agendaItem parts
*/
@@ -272,4 +273,12 @@
protected void setContext(final PropagationContext context) {
this.context = context;
}
+
+ public boolean isWasFired() {
+ return wasFired;
+ }
+
+ public void setWasFired( boolean wasFired ) {
+ this.wasFired = wasFired;
+ }
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -67,218 +67,234 @@
* @see java.io.Serializable
*
*/
-class LeapsWorkingMemory extends AbstractWorkingMemory
- implements
- EventSupport,
- PropertyChangeListener {
+class LeapsWorkingMemory extends AbstractWorkingMemory implements EventSupport,
+ PropertyChangeListener {
private static final long serialVersionUID = 320;
private final Map queryResults;
- private final IdentityMap leapsRulesToHandlesMap = new IdentityMap();
+ private final IdentityMap leapsRulesToHandlesMap = new IdentityMap( );
- private final IdentityMap rulesActivationsMap = new IdentityMap();
+ private final IdentityMap rulesActivationsMap = new IdentityMap( );
+ private final LinkedList noPositiveColumnsRules = new LinkedList( );
+
/**
* Construct.
*
* @param ruleBase
* The backing rule-base.
*/
- public LeapsWorkingMemory(final int id,
- final InternalRuleBase ruleBase) {
- super( id,
- ruleBase,
- ruleBase.newFactHandleFactory() );
- this.queryResults = new HashMap();
+ public LeapsWorkingMemory(final int id, final InternalRuleBase ruleBase) {
+ super( id, ruleBase, ruleBase.newFactHandleFactory( ) );
+ this.queryResults = new HashMap( );
this.agenda = new LeapsAgenda( this );
}
- public void doAssertObject(final InternalFactHandle factHandle,
- final Object object,
- final PropagationContext propagationContext) throws FactException {
+ public void doAssertObject( final InternalFactHandle factHandle,
+ final Object object,
+ final PropagationContext propagationContext )
+ throws FactException {
- this.pushTokenOnStack( factHandle,
- new Token( this,
- factHandle,
- propagationContext ) );
+ this.pushTokenOnStack( factHandle, new Token( this, factHandle, propagationContext ) );
// determine what classes it belongs to put it into the "table" on
// class name key
- final Class objectClass = object.getClass();
- for ( final Iterator tables = this.getFactTablesList( objectClass ).iterator(); tables.hasNext(); ) {
- final FactTable factTable = (FactTable) tables.next();
+ List tuplesToAssert = new LinkedList( );
+ final Object objectClass = LeapsBuilder.getLeapsClassType( object );
+ for (final Iterator tables = this.getFactTablesList( objectClass ).iterator( ); tables.hasNext( );) {
+ tuplesToAssert.clear( );
+ final FactTable factTable = (FactTable) tables.next( );
// adding fact to container
factTable.add( factHandle );
- // inspect all tuples for exists and not conditions and activate
- // /
- // deactivate agenda items
- for ( final Iterator tuples = factTable.getTuplesIterator(); tuples.hasNext(); ) {
- final LeapsTuple tuple = (LeapsTuple) tuples.next();
- boolean tupleWasReadyForActivation = tuple.isReadyForActivation();
- if ( !tuple.isActivationNull() ) {
- // check not constraints only on activated tuples to see
- // if
- // we need to deactivate
- final ColumnConstraints[] not = tuple.getLeapsRule().getNotColumnConstraints();
- for ( int i = 0, length = not.length; i < length; i++ ) {
- final ColumnConstraints constraint = not[i];
- if ( !tuple.isBlockingNotFactHandle( i ) && constraint.getClassType().isAssignableFrom( objectClass ) && constraint.isAllowed( factHandle,
- tuple,
- this ) ) {
- tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle,
- i );
- ((LeapsFactHandle) factHandle).addNotTuple( tuple,
- i );
- }
+ for (final Iterator tuples = factTable.getTuplesIterator( ); tuples.hasNext( );) {
+ final LeapsTuple tuple = (LeapsTuple) tuples.next( );
+
+ final ColumnConstraints[] not = tuple.getLeapsRule( )
+ .getNotColumnConstraints( );
+ for (int i = 0, length = not.length; i < length; i++) {
+ final ColumnConstraints constraint = not[i];
+ final Object columnClassObject = constraint.getClassType( );
+ if (!tuple.isBlockingNotFactHandle( i )
+ && ( ( objectClass.getClass( ) == Class.class
+ && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+ && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+ && constraint.isAllowed( factHandle, tuple, this )) {
+ tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
+ ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
}
- // check and see if we need de-activate
- if ( !tuple.isReadyForActivation() ) {
- if ( tuple.getLeapsRule().getRule() instanceof Query ) {
- // put query results to the working memory
- // location
- removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
- tuple );
- } else {
- // time to pull from agenda
- invalidateActivation( tuple );
- }
+ }
+ // check exists constraints and activate constraints
+ final ColumnConstraints[] exists = tuple.getLeapsRule( )
+ .getExistsColumnConstraints( );
+ for (int i = 0, length = exists.length; i < length; i++) {
+ final ColumnConstraints constraint = exists[i];
+ final Object columnClassObject = constraint.getClassType( );
+ if (!tuple.isExistsFactHandle( i )
+ && ( ( objectClass.getClass( ) == Class.class
+ && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+ && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+ && constraint.isAllowed( factHandle, tuple, this )) {
+ tuple.setExistsFactHandle( (LeapsFactHandle) factHandle, i );
+ ( (LeapsFactHandle) factHandle ).addExistsTuple( tuple, i );
}
- } else {
- // check exists constraints and activate constraints
- final ColumnConstraints[] exists = tuple.getLeapsRule().getExistsColumnConstraints();
- for ( int i = 0, length = exists.length; i < length; i++ ) {
- final ColumnConstraints constraint = exists[i];
- if ( !tuple.isExistsFactHandle( i ) && constraint.getClassType().isAssignableFrom( objectClass ) && constraint.isAllowed( factHandle,
- tuple,
- this ) ) {
- tuple.setExistsFactHandle( (LeapsFactHandle) factHandle,
- i );
- ((LeapsFactHandle) factHandle).addExistsTuple( tuple,
- i );
- }
+ }
+ // check and see if we need activate
+ // activate only if tuple was not ready for it before
+ if (tuple.isReadyForActivation( )) {
+ // ready to activate
+ tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
+ PropagationContext.ASSERTION,
+ tuple.getLeapsRule( )
+ .getRule( ),
+ null ) );
+ tuplesToAssert.add( tuple );
+ }
+ }
+ for (Iterator tuples = tuplesToAssert.iterator( ); tuples.hasNext( );) {
+ LeapsTuple tuple = (LeapsTuple) tuples.next( );
+ factTable.removeTuple( tuple );
+ this.assertTuple( tuple );
+ }
+ }
+ // inspect all tuples for exists and not conditions and activate
+ // deactivate agenda items
+ Activation[] activations = this.agenda.getActivations( );
+ for (int k = 0; k < activations.length; k++) {
+ boolean deActivate = false;
+ LeapsTuple tuple = (LeapsTuple) activations[k].getTuple( );
+ final ColumnConstraints[] not = tuple.getLeapsRule( ).getNotColumnConstraints( );
+ for (int i = 0, length = not.length; i < length; i++) {
+ final ColumnConstraints constraint = not[i];
+ final Object columnClassObject = constraint.getClassType( );
+ if (!tuple.isBlockingNotFactHandle( i )
+ && ( ( objectClass.getClass( ) == Class.class
+ && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+ && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+ && constraint.isAllowed( factHandle, tuple, this )) {
+ tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
+ ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
+ if (!deActivate) {
+ deActivate = true;
}
- // check and see if we need activate
- // activate only if tuple was not ready for it before
- if ( !tupleWasReadyForActivation && tuple.isReadyForActivation() ) {
- // ready to activate
- tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
- PropagationContext.ASSERTION,
- tuple.getLeapsRule().getRule(),
- null ) );
-
- this.assertTuple( tuple );
- }
}
}
+ // check and see if we need de-activate
+ if (deActivate) {
+ if (tuple.getLeapsRule( ).getRule( ) instanceof Query) {
+ // put query results to the working memory
+ // location
+ removeFromQueryResults( tuple.getLeapsRule( ).getRule( ).getName( ),
+ tuple );
+ }
+ else {
+ // time to pull from agenda
+ invalidateActivation( tuple );
+ }
+ }
}
}
/**
- * copies reteoo behaviour in regards to logical assertion
- * and does checking on available tuples to see if any needs
- * invalidation / activation as a result of this retraction
+ * copies reteoo behaviour in regards to logical assertion and does checking
+ * on available tuples to see if any needs invalidation / activation as a
+ * result of this retraction
*
* @see WorkingMemory
*/
- public void doRetract(final InternalFactHandle factHandle,
- final PropagationContext propagationContext) {
+ public void doRetract( final InternalFactHandle factHandle,
+ final PropagationContext propagationContext ) {
/*
* leaps specific actions
*/
// remove fact from all relevant fact tables container
- for ( final Iterator it = this.getFactTablesList( factHandle.getObject().getClass() ).iterator(); it.hasNext(); ) {
- ((FactTable) it.next()).remove( factHandle );
+ for (final Iterator it = this.getFactTablesList( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
+ .iterator( ); it.hasNext( );) {
+ ( (FactTable) it.next( ) ).remove( factHandle );
}
// 0. remove activated tuples
- final Iterator tuples = ((LeapsFactHandle) factHandle).getActivatedTuples();
- for ( ; tuples != null && tuples.hasNext(); ) {
- final LeapsTuple tuple = (LeapsTuple) tuples.next();
- if ( tuple.getLeapsRule().getRule() instanceof Query ) {
+ final Iterator tuples = ( (LeapsFactHandle) factHandle ).getActivatedTuples( );
+ for (; tuples != null && tuples.hasNext( );) {
+ final LeapsTuple tuple = (LeapsTuple) tuples.next( );
+ if (tuple.getLeapsRule( ).getRule( ) instanceof Query) {
// put query results to the working memory location
- removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
- tuple );
- } else {
+ removeFromQueryResults( tuple.getLeapsRule( ).getRule( ).getName( ), tuple );
+ }
+ else {
// time to pull from agenda
invalidateActivation( tuple );
}
}
// 1. remove fact for nots and exists tuples
- final IdentityMap tuplesNotReadyForActivation = new IdentityMap();
+ final IdentityMap tuplesNotReadyForActivation = new IdentityMap( );
FactHandleTupleAssembly assembly;
LeapsTuple tuple;
Iterator it;
- it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
- if ( it != null ) {
- for ( ; it.hasNext(); ) {
- assembly = (FactHandleTupleAssembly) it.next();
- tuple = assembly.getTuple();
- if ( !tuple.isReadyForActivation() ) {
- tuplesNotReadyForActivation.put( tuple,
- tuple );
+ it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
+ if (it != null) {
+ for (; it.hasNext( );) {
+ assembly = (FactHandleTupleAssembly) it.next( );
+ tuple = assembly.getTuple( );
+ if (!tuple.isReadyForActivation( )) {
+ tuplesNotReadyForActivation.put( tuple, tuple );
}
- tuple.removeBlockingNotFactHandle( assembly.getIndex() );
+ tuple.removeBlockingNotFactHandle( assembly.getIndex( ) );
TokenEvaluator.evaluateNotCondition( (LeapsFactHandle) factHandle,
- // TokenEvaluator.evaluateNotCondition( new LeapsFactHandle( factHandle.getRecency( ) + 1,
- // new Object( ) ),
- assembly.getIndex(),
+ // TokenEvaluator.evaluateNotCondition( new LeapsFactHandle(
+ // factHandle.getRecency( ) + 1,
+ // new Object( ) ),
+ assembly.getIndex( ),
tuple,
this );
}
}
- it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
- if ( it != null ) {
- for ( ; it.hasNext(); ) {
- assembly = (FactHandleTupleAssembly) it.next();
- tuple = assembly.getTuple();
- if ( !tuple.isReadyForActivation() ) {
- tuplesNotReadyForActivation.put( tuple,
- tuple );
+ it = ( (LeapsFactHandle) factHandle ).getExistsTupleAssemblies( );
+ if (it != null) {
+ for (; it.hasNext( );) {
+ assembly = (FactHandleTupleAssembly) it.next( );
+ tuple = assembly.getTuple( );
+ if (!tuple.isReadyForActivation( )) {
+ tuplesNotReadyForActivation.put( tuple, tuple );
}
- tuple.removeExistsFactHandle( assembly.getIndex() );
+ tuple.removeExistsFactHandle( assembly.getIndex( ) );
TokenEvaluator.evaluateExistsCondition( (LeapsFactHandle) factHandle,
- // TokenEvaluator.evaluateExistsCondition( new LeapsFactHandle( factHandle.getRecency( ) + 1,
- // null ),
- assembly.getIndex(),
+ // TokenEvaluator.evaluateExistsCondition( new LeapsFactHandle(
+ // factHandle.getRecency( ) + 1,
+ // null ),
+ assembly.getIndex( ),
tuple,
this );
}
}
// 2. assert all tuples that are ready for activation or cancel ones
// that are no longer
- final IteratorChain chain = new IteratorChain();
- it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
- if ( it != null ) {
+ final IteratorChain chain = new IteratorChain( );
+ it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
+ if (it != null) {
chain.addIterator( it );
}
- it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
- if ( it != null ) {
+ it = ( (LeapsFactHandle) factHandle ).getExistsTupleAssemblies( );
+ if (it != null) {
chain.addIterator( it );
}
- for ( ; chain.hasNext(); ) {
- tuple = ((FactHandleTupleAssembly) chain.next()).getTuple();
+ for (; chain.hasNext( );) {
+ tuple = ( (FactHandleTupleAssembly) chain.next( ) ).getTuple( );
// can assert only tuples that were not eligible for activation
// before retraction
- if ( tuple.isReadyForActivation() && tuple.isActivationNull() && tuplesNotReadyForActivation.containsKey( tuple ) ) {
+ if (tuple.isReadyForActivation( )) {
// ready to activate
- tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+ tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
PropagationContext.ASSERTION,
- tuple.getLeapsRule().getRule(),
+ tuple.getLeapsRule( )
+ .getRule( ),
null ) );
+ this.getFactTable( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
+ .removeTuple( tuple );
this.assertTuple( tuple );
- } else {
- if ( tuple.getLeapsRule().getRule() instanceof Query ) {
- // put query results to the working memory location
- removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
- tuple );
- } else {
- // time to pull from agenda
- invalidateActivation( tuple );
- }
}
}
@@ -287,80 +303,81 @@
}
/**
- * used when assertion / retraction adds invalidating conditions that
- * make tuple ineligible for firing
+ * used when assertion / retraction adds invalidating conditions that make
+ * tuple ineligible for firing
*
* @param tuple
*/
- private final void invalidateActivation(final LeapsTuple tuple) {
- final Activation activation = tuple.getActivation();
- if ( !tuple.isReadyForActivation() && !tuple.isActivationNull() ) {
+ private final void invalidateActivation( final LeapsTuple tuple ) {
+ final Activation activation = tuple.getActivation( );
+ if (!tuple.isReadyForActivation( ) && !tuple.isActivationNull( )) {
// invalidate agenda agendaItem
- if ( activation.isActivated() ) {
- activation.remove();
- getAgendaEventSupport().fireActivationCancelled( activation );
+ if (activation.isActivated( )) {
+ activation.remove( );
+ getAgendaEventSupport( ).fireActivationCancelled( activation );
}
//
tuple.setActivation( null );
}
- if ( activation != null ) {
+ if (activation != null) {
// remove logical dependency
this.tms.removeLogicalDependencies( activation,
- tuple.getContext(),
- tuple.getLeapsRule().getRule() );
+ tuple.getContext( ),
+ tuple.getLeapsRule( ).getRule( ) );
// remove from rule / activaitons map
- FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule() );
- if ( activations != null ) {
+ FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule( ) );
+ if (activations != null) {
activations.remove( activation );
}
}
}
/**
- * modify is implemented as half way retract / assert due to the truth maintenance issues.
+ * modify is implemented as half way retract / assert due to the truth
+ * maintenance issues.
*
* @see WorkingMemory
*/
- public void modifyObject(final FactHandle factHandle,
- final Object object,
- final Rule rule,
- final Activation activation) throws FactException {
+ public void modifyObject( final FactHandle factHandle,
+ final Object object,
+ final Rule rule,
+ final Activation activation ) throws FactException {
try {
- this.getLock().lock();
+ this.getLock( ).lock( );
final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
PropagationContext.MODIFICATION,
rule,
activation );
- final int status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
+ final int status = ( (InternalFactHandle) factHandle ).getEqualityKey( )
+ .getStatus( );
final Object originalObject = this.assertMap.remove( factHandle );
- if ( originalObject == null ) {
+ if (originalObject == null) {
throw new NoSuchFactObjectException( factHandle );
}
//
// do subset of retractObject( )
//
final InternalFactHandle handle = (InternalFactHandle) factHandle;
- if ( handle.getId() == -1 ) {
+ if (handle.getId( ) == -1) {
// can't retract an already retracted handle
return;
}
removePropertyChangeListener( handle );
- doRetract( handle,
- propagationContext );
+ doRetract( handle, propagationContext );
// Update the equality key, which maintains a list of stated
// FactHandles
- final EqualityKey key = handle.getEqualityKey();
+ final EqualityKey key = handle.getEqualityKey( );
key.removeFactHandle( handle );
handle.setEqualityKey( null );
// If the equality key is now empty, then remove it
- if ( key.isEmpty() ) {
+ if (key.isEmpty( )) {
this.tms.remove( key );
}
// produces NPE otherwise
@@ -370,23 +387,21 @@
// and now assert
//
/* check to see if this is a logically asserted object */
- this.assertObject( object,
- false,
- (status == EqualityKey.STATED) ? false : true,
- rule,
- activation );
+ this.assertObject( object, false, ( status == EqualityKey.STATED ) ? false
+ : true, rule, activation );
this.workingMemoryEventSupport.fireObjectModified( propagationContext,
handle,
- handle.getObject(),
+ handle.getObject( ),
object );
- if ( !this.factQueue.isEmpty() ) {
- propagateQueuedActions();
+ if (!this.factQueue.isEmpty( )) {
+ propagateQueuedActions( );
}
- } finally {
- this.getLock().unlock();
}
+ finally {
+ this.getLock( ).unlock( );
+ }
}
/**
@@ -397,7 +412,7 @@
/**
* algorithm stack.
*/
- private final TokenStack mainStack = new TokenStack();
+ private final TokenStack mainStack = new TokenStack( );
/**
* generates or just return List of internal factTables that correspond a
@@ -405,20 +420,25 @@
*
* @return
*/
- protected final List getFactTablesList(final Class c) {
- final ArrayList list = new ArrayList();
- // interfaces
- final Class[] interfaces = c.getInterfaces();
- for ( int i = 0; i < interfaces.length; i++ ) {
- list.add( this.getFactTable( interfaces[i] ) );
+ protected final List getFactTablesList( final Object objectClass ) {
+ final ArrayList list = new ArrayList( );
+ if (objectClass.getClass( ) == Class.class) {
+ // interfaces
+ final Class[] interfaces = ( (Class) objectClass ).getInterfaces( );
+ for (int i = 0; i < interfaces.length; i++) {
+ list.add( this.getFactTable( interfaces[i] ) );
+ }
+ // classes
+ Class bufClass = (Class) objectClass;
+ while (bufClass != null) {
+ //
+ list.add( this.getFactTable( bufClass ) );
+ // and get the next class on the list
+ bufClass = bufClass.getSuperclass( );
+ }
}
- // classes
- Class bufClass = c;
- while ( bufClass != null ) {
- //
- list.add( this.getFactTable( bufClass ) );
- // and get the next class on the list
- bufClass = bufClass.getSuperclass();
+ else {
+ list.add( this.getFactTable( objectClass ) );
}
return list;
}
@@ -426,30 +446,33 @@
/**
* adds new leaps token on main stack
*
- * @param fact handle
+ * @param fact
+ * handle
* @param token
*/
- protected final void pushTokenOnStack(final InternalFactHandle factHandle,
- final Token token) {
+ protected final void pushTokenOnStack( final InternalFactHandle factHandle,
+ final Token token ) {
this.mainStack.push( token );
}
/**
* removes leaps token on main stack
*
- * @param fact handle
+ * @param fact
+ * handle
*/
- protected final void removeTokenFromStack(final LeapsFactHandle factHandle) {
- this.mainStack.remove( factHandle.getId() );
+ protected final void removeTokenFromStack( final LeapsFactHandle factHandle ) {
+ this.mainStack.remove( factHandle.getId( ) );
}
/**
* gets leaps token from top of stack
*
- * @param fact handle
+ * @param fact
+ * handle
*/
protected final Token peekTokenOnTop() {
- return (Token) this.mainStack.peek();
+ return (Token) this.mainStack.peek( );
}
/**
@@ -459,24 +482,28 @@
* of objects
* @return fact table of requested class type
*/
- protected FactTable getFactTable(final Class c) {
+ protected FactTable getFactTable( final Object objectClass ) {
FactTable table;
- if ( this.factTables.containsKey( c ) ) {
- table = (FactTable) this.factTables.get( c );
- } else {
- table = new FactTable( DefaultConflictResolver.getInstance() );
- this.factTables.put( c,
- table );
+ if (this.factTables.containsKey( objectClass )) {
+ table = (FactTable) this.factTables.get( objectClass );
+ }
+ else {
+ table = new FactTable( DefaultConflictResolver.getInstance( ) );
+ this.factTables.put( objectClass, table );
// review existing rules and assign to the fact table if needed
- for ( final Iterator iter = this.leapsRulesToHandlesMap.keySet().iterator(); iter.hasNext(); ) {
- final LeapsRule leapsRule = (LeapsRule) iter.next();
- if ( leapsRule.getNumberOfColumns() > 0 ) {
+ for (final Iterator iter = this.leapsRulesToHandlesMap.keySet( ).iterator( ); iter.hasNext( );) {
+ final LeapsRule leapsRule = (LeapsRule) iter.next( );
+ if (leapsRule.getNumberOfColumns( ) > 0) {
final List rulesHandles = (List) this.leapsRulesToHandlesMap.get( leapsRule );
- for ( final Iterator handles = rulesHandles.iterator(); handles.hasNext(); ) {
- final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next();
- if ( leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition() ).isAssignableFrom( c ) ) {
- table.addRule( this,
- handle );
+ for (final Iterator handles = rulesHandles.iterator( ); handles.hasNext( );) {
+ final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next( );
+ final Object columnClassObject = leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition( ) );
+ if (( objectClass.getClass( ) == Class.class
+ && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) )
+ // on template name
+ || ( objectClass.getClass( ) != Class.class
+ && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) )) {
+ table.addRule( this, handle );
}
}
}
@@ -491,142 +518,181 @@
*
* @param rules
*/
- protected void addLeapsRules(final List rules) {
- this.getLock().lock();
+ protected void addLeapsRules( final List rules ) {
+ this.getLock( ).lock( );
try {
ArrayList ruleHandlesList;
LeapsRule rule;
LeapsRuleHandle ruleHandle;
- for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
- rule = (LeapsRule) it.next();
+ for (final Iterator it = rules.iterator( ); it.hasNext( );) {
+ rule = (LeapsRule) it.next( );
+ // create hashed entries for not and exists
+ // check for NOT and EXISTS and create new hashed entry
+ ColumnConstraints constraint;
+ for (int i = 0; i < rule.getNumberOfNotColumns( ); i++) {
+ constraint = rule.getNotColumnConstraints( )[i];
+ this.getFactTable( constraint.getClassType( ) )
+ .createHashedSubTable( constraint );
+ }
+ for (int i = 0; i < rule.getNumberOfExistsColumns( ); i++) {
+ constraint = rule.getExistsColumnConstraints( )[i];
+ this.getFactTable( constraint.getClassType( ) )
+ .createHashedSubTable( constraint );
+ }
// some times rules do not have "normal" constraints and only
// not and exists
- if ( rule.getNumberOfColumns() > 0 ) {
- ruleHandlesList = new ArrayList();
- for ( int i = 0; i < rule.getNumberOfColumns(); i++ ) {
- ruleHandle = new LeapsRuleHandle( ((LeapsFactHandleFactory) this.handleFactory).getNextId(),
+ if (rule.getNumberOfColumns( ) > 0) {
+ ruleHandlesList = new ArrayList( );
+ for (int i = 0; i < rule.getNumberOfColumns( ); i++) {
+ ruleHandle = new LeapsRuleHandle( ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( ),
rule,
i );
//
- this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) ).addRule( this,
- ruleHandle );
- //
+ if (rule.getColumnConstraintsAtPosition( i ).getClass( ) != FromConstraint.class) {
+ this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) )
+ .addRule( this, ruleHandle );
+ //
+ }
+ else {
+ FactTable table = this.getFactTable( FromConstraintFactDriver.class );
+ table.addRule( this, ruleHandle );
+ if (table.isEmpty( )) {
+ this.assertObject( new FromConstraintFactDriver( ) );
+ }
+ }
ruleHandlesList.add( ruleHandle );
}
- this.leapsRulesToHandlesMap.put( rule,
- ruleHandlesList );
- } else {
- // to pick up rules that do not require columns, only not
- // and exists
- final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter(),
- PropagationContext.ASSERTION,
- null,
- null );
-
- TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
- rule,
- context ),
- rule,
- this );
+ this.leapsRulesToHandlesMap.put( rule, ruleHandlesList );
}
+ else {
+ this.noPositiveColumnsRules.add( new LeapsRuleHandle( ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( ),
+ rule,
+ 0 ) );
+ }
}
- } finally {
- this.getLock().unlock();
}
+ finally {
+ this.getLock( ).unlock( );
+ }
}
- protected void removeRule(final List rules) {
- this.getLock().lock();
+ protected void removeRule( final List rules ) {
+ this.getLock( ).lock( );
try {
ArrayList ruleHandlesList;
LeapsRule leapsRule;
LeapsRuleHandle ruleHandle;
- for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
- leapsRule = (LeapsRule) it.next();
+ for (final Iterator it = rules.iterator( ); it.hasNext( );) {
+ leapsRule = (LeapsRule) it.next( );
// some times rules do not have "normal" constraints and only
// not and exists
- if ( leapsRule.getNumberOfColumns() > 0 ) {
+ if (leapsRule.getNumberOfColumns( ) > 0) {
ruleHandlesList = (ArrayList) this.leapsRulesToHandlesMap.remove( leapsRule );
- for ( int i = 0; i < ruleHandlesList.size(); i++ ) {
+ for (int i = 0; i < ruleHandlesList.size( ); i++) {
ruleHandle = (LeapsRuleHandle) ruleHandlesList.get( i );
//
- this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) ).removeRule( this,
- ruleHandle );
+ this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) )
+ .removeRule( this, ruleHandle );
}
}
//
}
- final Rule rule = ((LeapsRule) rules.get( 0 )).getRule();
+ final Rule rule = ( (LeapsRule) rules.get( 0 ) ).getRule( );
final FastMap activations = (FastMap) this.rulesActivationsMap.remove( rule );
- if ( activations != null ) {
- for ( final Iterator activationsIt = activations.keySet().iterator(); activationsIt.hasNext(); ) {
- final Activation activation = (Activation) activationsIt.next();
- ((LeapsTuple) activation.getTuple()).setActivation( null );
+ if (activations != null) {
+ for (final Iterator activationsIt = activations.keySet( ).iterator( ); activationsIt.hasNext( );) {
+ final Activation activation = (Activation) activationsIt.next( );
+ ( (LeapsTuple) activation.getTuple( ) ).setActivation( null );
this.tms.removeLogicalDependencies( activation,
- activation.getPropagationContext(),
+ activation.getPropagationContext( ),
rule );
}
}
- propagateQueuedActions();
- } finally {
- this.getLock().unlock();
+ propagateQueuedActions( );
}
+ finally {
+ this.getLock( ).unlock( );
+ }
}
/**
* main loop
*
*/
- public final synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
+ public final synchronized void fireAllRules( final AgendaFilter agendaFilter )
+ throws FactException {
// If we're already firing a rule, then it'll pick up
// the firing for any other assertObject(..) that get
// nested inside, avoiding concurrent-modification
// exceptions, depending on code paths of the actions.
- if ( !this.firing ) {
+ if (!this.firing) {
try {
this.firing = true;
boolean nothingToProcess = false;
- while ( !nothingToProcess ) {
+ while (!nothingToProcess) {
+ // check for the initial fact
+ for (Iterator rulesIt = this.noPositiveColumnsRules.iterator( ); rulesIt.hasNext( );) {
+ LeapsRule rule = ( (LeapsRuleHandle) rulesIt.next( ) ).getLeapsRule( );
+ final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter( ),
+ PropagationContext.ASSERTION,
+ null,
+ null );
+ TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
+ rule,
+ context ),
+ rule,
+ this );
+
+ }
+ this.noPositiveColumnsRules.clear( );
// normal rules with required columns
- while ( !this.mainStack.empty() ) {
- final Token token = this.peekTokenOnTop();
+ while (!this.mainStack.empty( )) {
+ final Token token = this.peekTokenOnTop( );
boolean done = false;
- while ( !done ) {
- if ( !token.isResume() ) {
- if ( token.hasNextRuleHandle() ) {
- token.nextRuleHandle();
- } else {
+ while (!done) {
+ if (!token.isResume( )) {
+ if (token.hasNextRuleHandle( )) {
+ token.nextRuleHandle( );
+ }
+ else {
// we do not pop because something might get
// asserted
// and placed on hte top of the stack during
// firing
- this.removeTokenFromStack( (LeapsFactHandle) token.getDominantFactHandle() );
+ this.removeTokenFromStack( (LeapsFactHandle) token.getDominantFactHandle( ) );
done = true;
}
}
- if ( !done ) {
+ if (!done) {
try {
- // ok. now we have tuple, dominant fact and
- // rules and ready to seek to checks if any
+ // ok. now we have tuple, dominant fact
+ // and
+ // rules and ready to seek to checks if
+ // any
// agendaItem
// matches on current rule
TokenEvaluator.evaluate( token );
// something was found so set marks for
// resume processing
- if ( token.getDominantFactHandle() != null ) {
- token.setResume( true );
+ if (token.getDominantFactHandle( ) != null) {
+ if (token.getDominantFactHandle( )
+ .getObject( )
+ .getClass( ) != FromConstraintFactDriver.class) {
+ token.setResume( true );
+ }
done = true;
}
- } catch ( final NoMatchesFoundException ex ) {
+ }
+ catch (final NoMatchesFoundException ex) {
token.setResume( false );
}
}
// we put everything on agenda
// and if there is no modules or anything like it
// it would fire just activated rule
- while ( this.agenda.fireNextItem( agendaFilter ) ) {
+ while (this.agenda.fireNextItem( agendaFilter )) {
;
}
}
@@ -634,20 +700,23 @@
// pick activations generated by retraction or assert
// can generate activations off exists and not pending
// tuples
- while ( this.agenda.fireNextItem( agendaFilter ) ) {
+ while (this.agenda.fireNextItem( agendaFilter )) {
;
}
- if ( this.mainStack.empty() ) {
+ if (this.mainStack.empty( )) {
nothingToProcess = true;
}
}
// mark when method was called last time
- this.idLastFireAllAt = ((LeapsFactHandleFactory) this.handleFactory).getNextId();
+ this.idLastFireAllAt = ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( );
// set all factTables to be reseeded
- for ( final Iterator it = this.factTables.values().iterator(); it.hasNext(); ) {
- ((FactTable) it.next()).setReseededStack( true );
+ for (final Iterator it = this.factTables.values( ).iterator( ); it.hasNext( );) {
+ ( (FactTable) it.next( ) ).setReseededStack( true );
}
- } finally {
+ // clear table that is used to trigger From constraints
+ this.getFactTable( FromConstraintFactDriver.class ).clear( );
+ }
+ finally {
this.firing = false;
}
}
@@ -662,14 +731,14 @@
Object key;
ret = ret + "\n" + "Working memory";
ret = ret + "\n" + "Fact Tables by types:";
- for ( final Iterator it = this.factTables.keySet().iterator(); it.hasNext(); ) {
- key = it.next();
+ for (final Iterator it = this.factTables.keySet( ).iterator( ); it.hasNext( );) {
+ key = it.next( );
ret = ret + "\n" + "****************** " + key;
- ret = ret + ((FactTable) this.factTables.get( key )).toString();
+ ret = ret + ( (FactTable) this.factTables.get( key ) ).toString( );
}
ret = ret + "\n" + "Stack:";
- for ( final Iterator it = this.mainStack.iterator(); it.hasNext(); ) {
- ret = ret + "\n" + "\t" + it.next();
+ for (final Iterator it = this.mainStack.iterator( ); it.hasNext( );) {
+ ret = ret + "\n" + "\t" + it.next( );
}
return ret;
}
@@ -684,20 +753,20 @@
* @throws AssertionException
* If an error occurs while asserting.
*/
- public final void assertTuple(final LeapsTuple tuple) {
- final PropagationContext context = tuple.getContext();
- final Rule rule = tuple.getLeapsRule().getRule();
+ public final void assertTuple( final LeapsTuple tuple ) {
+ final PropagationContext context = tuple.getContext( );
+ final Rule rule = tuple.getLeapsRule( ).getRule( );
// if the current Rule is no-loop and the origin rule is the same then
// return
- if ( rule.getNoLoop() && rule.equals( context.getRuleOrigin() ) ) {
+ if (rule.getNoLoop( ) && rule.equals( context.getRuleOrigin( ) )) {
return;
}
//
- final Duration dur = rule.getDuration();
+ final Duration dur = rule.getDuration( );
Activation agendaItem;
- if ( dur != null && dur.getDuration( tuple ) > 0 ) {
- agendaItem = new ScheduledAgendaItem( context.getPropagationNumber(),
+ if (dur != null && dur.getDuration( tuple ) > 0) {
+ agendaItem = new ScheduledAgendaItem( context.getPropagationNumber( ),
tuple,
this.agenda,
context,
@@ -705,25 +774,28 @@
this.agenda.scheduleItem( (ScheduledAgendaItem) agendaItem );
tuple.setActivation( agendaItem );
agendaItem.setActivated( true );
- this.getAgendaEventSupport().fireActivationCreated( agendaItem );
- } else {
- final LeapsRule leapsRule = tuple.getLeapsRule();
- AgendaGroupImpl agendaGroup = leapsRule.getAgendaGroup();
- if ( agendaGroup == null ) {
- if ( rule.getAgendaGroup() == null || rule.getAgendaGroup().equals( "" ) || rule.getAgendaGroup().equals( AgendaGroup.MAIN ) ) {
+ this.getAgendaEventSupport( ).fireActivationCreated( agendaItem );
+ }
+ else {
+ final LeapsRule leapsRule = tuple.getLeapsRule( );
+ AgendaGroupImpl agendaGroup = leapsRule.getAgendaGroup( );
+ if (agendaGroup == null) {
+ if (rule.getAgendaGroup( ) == null || rule.getAgendaGroup( ).equals( "" )
+ || rule.getAgendaGroup( ).equals( AgendaGroup.MAIN )) {
// Is the Rule AgendaGroup undefined? If it is use MAIN,
// which is added to the Agenda by default
agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( AgendaGroup.MAIN );
- } else {
+ }
+ else {
// AgendaGroup is defined, so try and get the AgendaGroup
// from the Agenda
- agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup() );
+ agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup( ) );
}
- if ( agendaGroup == null ) {
+ if (agendaGroup == null) {
// The AgendaGroup is defined but not yet added to the
// Agenda, so create the AgendaGroup and add to the Agenda.
- agendaGroup = new AgendaGroupImpl( rule.getAgendaGroup() );
+ agendaGroup = new AgendaGroupImpl( rule.getAgendaGroup( ) );
this.agenda.addAgendaGroup( agendaGroup );
}
@@ -731,11 +803,11 @@
}
// set the focus if rule autoFocus is true
- if ( rule.getAutoFocus() ) {
+ if (rule.getAutoFocus( )) {
this.agenda.setFocus( agendaGroup );
}
- agendaItem = new AgendaItem( context.getPropagationNumber(),
+ agendaItem = new AgendaItem( context.getPropagationNumber( ),
tuple,
context,
rule );
@@ -744,30 +816,28 @@
tuple.setActivation( agendaItem );
agendaItem.setActivated( true );
- this.getAgendaEventSupport().fireActivationCreated( agendaItem );
+ this.getAgendaEventSupport( ).fireActivationCreated( agendaItem );
}
// retract support
- final LeapsFactHandle[] factHandles = (LeapsFactHandle[]) tuple.getFactHandles();
- for ( int i = 0; i < factHandles.length; i++ ) {
+ final LeapsFactHandle[] factHandles = (LeapsFactHandle[]) tuple.getFactHandles( );
+ for (int i = 0; i < factHandles.length; i++) {
factHandles[i].addActivatedTuple( tuple );
}
// rules remove support
FastMap activations = (FastMap) this.rulesActivationsMap.get( rule );
- if ( activations == null ) {
- activations = new FastMap();
- this.rulesActivationsMap.put( rule,
- activations );
+ if (activations == null) {
+ activations = new FastMap( );
+ this.rulesActivationsMap.put( rule, activations );
}
- activations.put( agendaItem,
- agendaItem );
+ activations.put( agendaItem, agendaItem );
}
List getActivations() {
- List ret = new ArrayList();
- for ( final Iterator it = this.rulesActivationsMap.values().iterator(); it.hasNext(); ) {
- ret.addAll( ((FastMap) it.next()).values() );
+ List ret = new ArrayList( );
+ for (final Iterator it = this.rulesActivationsMap.values( ).iterator( ); it.hasNext( );) {
+ ret.addAll( ( (FastMap) it.next( ) ).values( ) );
}
return ret;
@@ -777,42 +847,38 @@
return ++this.propagationIdCounter;
}
- public QueryResults getQueryResults(final String queryName) {
+ public QueryResults getQueryResults( final String queryName ) {
final IdentityMap map = (IdentityMap) this.queryResults.get( queryName );
- if ( map == null ) {
+ if (map == null) {
return null;
}
- final LinkedList list = new LinkedList();
- for ( final Iterator it = map.keySet().iterator(); it.hasNext(); ) {
- list.add( it.next() );
+ final LinkedList list = new LinkedList( );
+ for (final Iterator it = map.keySet( ).iterator( ); it.hasNext( );) {
+ list.add( it.next( ) );
}
- if ( !list.isEmpty() ) {
- final Query queryRule = (Query) ((LeapsTuple) list.get( 0 )).getLeapsRule().getRule();
- return new LeapsQueryResults( list,
- queryRule,
- this );
- } else {
+ if (!list.isEmpty( )) {
+ final Query queryRule = (Query) ( (LeapsTuple) list.get( 0 ) ).getLeapsRule( )
+ .getRule( );
+ return new LeapsQueryResults( list, queryRule, this );
+ }
+ else {
return null;
}
}
- void addToQueryResults(final String query,
- final Tuple tuple) {
+ void addToQueryResults( final String query, final Tuple tuple ) {
IdentityMap map = (IdentityMap) this.queryResults.get( query );
- if ( map == null ) {
- map = new IdentityMap();
- this.queryResults.put( query,
- map );
+ if (map == null) {
+ map = new IdentityMap( );
+ this.queryResults.put( query, map );
}
- map.put( tuple,
- tuple );
+ map.put( tuple, tuple );
}
- void removeFromQueryResults(final String query,
- final Tuple tuple) {
+ void removeFromQueryResults( final String query, final Tuple tuple ) {
final IdentityMap map = (IdentityMap) this.queryResults.get( query );
- if ( map != null ) {
+ if (map != null) {
map.remove( tuple );
}
}
@@ -820,34 +886,31 @@
/**
* to store facts to cursor over it
*/
- private final Map factTables = new FactTables();
+ private final Map factTables = new FactTables( );
- class FactTables
- implements
- Map,
- Serializable {
- private LinkedList tables = new LinkedList();
+ class FactTables implements Map, Serializable {
+ private LinkedList tables = new LinkedList( );
- private HashMap map = new HashMap();
+ private HashMap map = new HashMap( );
public int size() {
- return this.tables.size();
+ return this.tables.size( );
}
public void clear() {
- this.tables.clear();
- this.map.clear();
+ this.tables.clear( );
+ this.map.clear( );
}
public boolean isEmpty() {
- return this.tables.isEmpty();
+ return this.tables.isEmpty( );
}
- public boolean containsKey(Object key) {
+ public boolean containsKey( Object key ) {
return this.map.containsKey( key );
}
- public boolean containsValue(Object value) {
+ public boolean containsValue( Object value ) {
return this.map.containsValue( value );
}
@@ -855,36 +918,37 @@
return this.tables;
}
- public void putAll(Map t) {
- this.tables.addAll( t.values() );
+ public void putAll( Map t ) {
+ this.tables.addAll( t.values( ) );
this.map.putAll( t );
}
public Set entrySet() {
- return this.map.entrySet();
+ return this.map.entrySet( );
}
public Set keySet() {
- return this.map.keySet();
+ return this.map.keySet( );
}
- public Object get(Object key) {
+ public Object get( Object key ) {
return this.map.get( key );
}
- public Object remove(Object key) {
+ public Object remove( Object key ) {
Object ret = this.map.remove( key );
this.tables.remove( ret );
return ret;
}
- public Object put(Object key,
- Object value) {
+ public Object put( Object key, Object value ) {
this.tables.add( value );
- this.map.put( key,
- value );
+ this.map.put( key, value );
return value;
}
}
+
+ private class FromConstraintFactDriver implements Serializable {
+ }
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -70,8 +70,7 @@
private Iterator rulesIterator() {
if (this.rules == null) {
if (this.dominantFactHandle != null) {
- this.rules = this.workingMemory.getFactTable( this.dominantFactHandle.getObject( )
- .getClass( ) )
+ this.rules = this.workingMemory.getFactTable( LeapsBuilder.getLeapsClassType( this.dominantFactHandle.getObject( ) ) )
.getRulesIterator( );
}
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -16,11 +16,15 @@
* limitations under the License.
*/
+import java.util.Iterator;
+
+import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.leaps.util.Table;
import org.drools.leaps.util.TableIterator;
import org.drools.rule.EvalCondition;
import org.drools.rule.InvalidRuleException;
+import org.drools.spi.Tuple;
/**
* helper class that does condition evaluation on token when working memory does
@@ -51,34 +55,41 @@
final InternalFactHandle dominantFactHandle = token.getDominantFactHandle( );
if (leapsRule.getColumnConstraintsAtPosition( dominantFactPosition )
.isAllowedAlpha( dominantFactHandle, token, workingMemory )) {
- final Class dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
+ final Object dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
final TableIterator[] iterators = new TableIterator[numberOfColumns];
// getting iterators first
for (int i = 0; i < numberOfColumns; i++) {
- if (i == dominantFactPosition) {
- iterators[i] = Table.singleItemIterator( dominantFactHandle );
- }
- else {
- final Class columnClass = leapsRule.getColumnClassObjectTypeAtPosition( i );
- final ColumnConstraints constraints = leapsRule.getColumnConstraintsAtPosition( i );
- final FactTable factTable = workingMemory.getFactTable( columnClass );
- final LeapsFactHandle startFactHandle = ( dominantClass == columnClass ) ? new LeapsFactHandle( dominantFactHandle.getRecency( ) - 1,
- new Object( ) )
- : (LeapsFactHandle) dominantFactHandle;
- //
- if (i > 0 && constraints.isAlphaPresent( )) {
- iterators[i] = factTable.constrainedIteratorFromPositionToTableStart( workingMemory,
- constraints,
- startFactHandle,
- ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
- : startFactHandle ) );
+ final Object columnClass = leapsRule.getColumnClassObjectTypeAtPosition( i );
+ final ColumnConstraints constraints = leapsRule.getColumnConstraintsAtPosition( i );
+ // we do not need iterators for From constraint
+ if (constraints.getClass( ) != FromConstraint.class) {
+ if (i == dominantFactPosition) {
+ iterators[i] = Table.singleItemIterator( dominantFactHandle );
}
else {
- iterators[i] = factTable.iteratorFromPositionToTableStart( startFactHandle,
- ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
- : startFactHandle ) );
+ final FactTable factTable = workingMemory.getFactTable( columnClass );
+ final LeapsFactHandle startFactHandle = ( dominantClass == columnClass ) ? new LeapsFactHandle( dominantFactHandle.getRecency( ) - 1,
+ new Object( ) )
+ : (LeapsFactHandle) dominantFactHandle;
+ if (i > 0 && constraints.isAlphaPresent( )) {
+ iterators[i] = factTable.constrainedIteratorFromPositionToTableStart( workingMemory,
+ constraints,
+ startFactHandle,
+ ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
+ : startFactHandle ) );
+ }
+ else {
+ iterators[i] = factTable.iteratorFromPositionToTableStart( startFactHandle,
+ ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
+ : startFactHandle ) );
+ }
}
}
+ else {
+ // we do not need iterator for from constraint
+ // it has its own
+ iterators[i] = null;
+ }
}
// check if any iterators are empty to abort
@@ -89,23 +100,28 @@
TableIterator currentIterator;
for (int i = 0; i < numberOfColumns; i++) {
currentIterator = iterators[i];
- // check if one of them is empty and immediate return
- if (currentIterator.isEmpty( )) {
- throw new NoMatchesFoundException( );
- }
- else {
- if (!doReset) {
- if (skip && currentIterator.hasNext( )
- && !currentIterator.peekNext( ).equals( token.get( i ) )) {
- // we tried to resume but our fact handle at marker
- // disappear no need to resume just reset all interators
- // positioned at the marker where we stoped last time
- skip = false;
- doReset = true;
- }
+ if (currentIterator != null) {
+ // check if one of them is empty and immediate return
+ if (currentIterator.isEmpty( )) {
+ throw new NoMatchesFoundException( );
}
else {
- currentIterator.reset( );
+ if (!doReset) {
+ if (skip && currentIterator.hasNext( )
+ && !currentIterator.peekNext( ).equals( token.get( i ) )) {
+ // we tried to resume but our fact handle at
+ // marker
+ // disappear no need to resume just reset all
+ // interators
+ // positioned at the marker where we stoped last
+ // time
+ skip = false;
+ doReset = true;
+ }
+ }
+ else {
+ currentIterator.reset( );
+ }
}
}
}
@@ -117,7 +133,8 @@
final int stopIteratingCount = numberOfColumns - 1;
while (!done) {
currentIterator = iterators[jj];
- if (!currentIterator.hasNext( )) {
+ // if it's not From and does not have next
+ if (currentIterator != null && !currentIterator.hasNext( )) {
if (jj == 0) {
done = true;
}
@@ -132,23 +149,38 @@
}
}
else {
- final LeapsFactHandle currentFactHandle = (LeapsFactHandle) currentIterator.next( );
- // check if match found we need to check only beta for
- // dominant fact
- // alpha was already checked
boolean localMatch = false;
- if (!skip) {
- if (jj != 0 || jj == dominantFactPosition) {
- localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
- .isAllowedBeta( currentFactHandle,
+ LeapsFactHandle currentFactHandle = null;
+ if (currentIterator != null) {
+ currentFactHandle = (LeapsFactHandle) currentIterator.next( );
+ // check if match found we need to check only beta for
+ // dominant fact
+ // alpha was already checked
+ if (!skip) {
+ if (jj != 0 || jj == dominantFactPosition) {
+ localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
+ .isAllowedBeta( currentFactHandle,
+ token,
+ workingMemory );
+ }
+ else {
+ localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
+ .isAllowed( currentFactHandle,
token,
workingMemory );
+ }
}
- else {
- localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
- .isAllowed( currentFactHandle,
- token,
- workingMemory );
+ }
+ else {
+ Object fromMatch = TokenEvaluator.evaluateFrom( (FromConstraint) leapsRule.getColumnConstraintsAtPosition( jj ),
+ token,
+ leapsRule,
+ workingMemory );
+ if (fromMatch != null) {
+ localMatch = true;
+ // this is not a real fact. just to make it work with
+ // token / tuple
+ currentFactHandle = new LeapsFactHandle( -1, fromMatch );
}
}
if (localMatch || skip) {
@@ -192,7 +224,7 @@
final LeapsRule leapsRule,
final LeapsWorkingMemory workingMemory ) {
if (leapsRule.containsEvalConditions( )
- && !TokenEvaluator.evaluateEvalConditions( leapsRule, tuple, workingMemory )) {
+ && !TokenEvaluator.evaluateEvalConditions( tuple, leapsRule, workingMemory )) {
return false;
}
if (leapsRule.containsExistsColumns( )) {
@@ -201,13 +233,6 @@
if (leapsRule.containsNotColumns( )) {
TokenEvaluator.evaluateNotConditions( tuple, leapsRule, workingMemory );
}
- // put tuple onto fact tables that might affect activation status
- // via exists or not conditions
- final Class[] classes = leapsRule.getExistsNotColumnsClasses( );
- for (int i = 0, length = classes.length; i < length; i++) {
- workingMemory.getFactTable( classes[i] ).addTuple( tuple );
- }
-
//
if (tuple.isReadyForActivation( )) {
// let agenda to do its work
@@ -215,6 +240,13 @@
return true;
}
else {
+ // put tuple onto fact tables that might affect activation status
+ // via exists or not conditions
+ final Class[] classes = leapsRule.getExistsNotColumnsClasses( );
+ for (int i = 0, length = classes.length; i < length; i++) {
+ workingMemory.getFactTable( classes[i] ).addTuple( tuple );
+ }
+
return false;
}
}
@@ -228,8 +260,30 @@
* @return
* @throws Exception
*/
- private final static boolean evaluateEvalConditions( final LeapsRule leapsRule,
- final LeapsTuple tuple,
+ private final static Object evaluateFrom( final FromConstraint from,
+ final Tuple tuple,
+ final LeapsRule leapsRule,
+ final LeapsWorkingMemory workingMemory ) {
+ for (Iterator it = from.getProvider( ).getResults( tuple, workingMemory, null ); it.hasNext( );) {
+ Object object = it.next( );
+ if (from.isAllowed( new DefaultFactHandle( -1, object ), tuple, workingMemory )) {
+ return object;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * checks is EvalConditions isAllowed()
+ *
+ * @param leapsRule
+ * @param tuple
+ * @param workingMemory
+ * @return
+ * @throws Exception
+ */
+ private final static boolean evaluateEvalConditions( final LeapsTuple tuple,
+ final LeapsRule leapsRule,
final LeapsWorkingMemory workingMemory ) {
final EvalCondition[] evals = leapsRule.getEvalConditions( );
for (int i = 0; i < evals.length; i++) {
@@ -257,10 +311,12 @@
final ColumnConstraints constraint = not[i];
// scan table starting at start fact handle
final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
- .reverseOrderIterator( );
+ .reverseOrderIterator( tuple, constraint );
+// .reverseOrderIterator( );
// stops if exists
boolean done = false;
- while (!done && tableIterator.hasNext( )) {
+ while (!done && tableIterator.hasNext( )) {
+// while (!done && tableIterator.hasNext( )) {
final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
// check constraint conditions
if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
@@ -290,7 +346,9 @@
// scan table starting at start fact handle
final ColumnConstraints constraint = rule.getNotColumnConstraints( )[index];
final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
- .iteratorFromPositionToTableEnd( startFactHandle );
+ .iteratorFromPositionToTableEnd( tuple, constraint, startFactHandle);
+// .iteratorFromPositionToTableEnd( startFactHandle );
+// .reverseOrderIterator( );
// stops if exists
boolean done = false;
while (!done && tableIterator.hasNext( )) {
@@ -319,7 +377,8 @@
final ColumnConstraints constraint = exists[i];
// scan table starting at start fact handle
final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
- .reverseOrderIterator( );
+ .reverseOrderIterator( tuple, constraint );
+// .reverseOrderIterator( );
// stop if exists
boolean done = false;
while (!done && tableIterator.hasNext( )) {
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -50,7 +50,7 @@
this.nextRecord = this.firstRecord;
}
- protected IteratorFromPositionToTableStart(final TableRecord startRecord,
+ public IteratorFromPositionToTableStart(final TableRecord startRecord,
final TableRecord currentRecord) {
this.firstRecord = startRecord;
this.nextRecord = currentRecord;
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -53,8 +53,8 @@
this.set = new TreeSet( new RecordComparator(comparator) );
}
- protected void clear() {
- this.headRecord = new TableRecord( null );
+ public void clear() {
+ this.headRecord = null;
this.empty = true;
this.count = 0;
this.set.clear( );
@@ -343,4 +343,8 @@
public static TableIterator singleItemIterator( final Object object ) {
return new IteratorFromPositionToTableStart( new TableRecord( object ) );
}
+
+ public static TableIterator emptyIterator() {
+ return new IteratorFromPositionToTableStart( null, null );
+ }
}
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,383 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.drools.DroolsTestCase;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.examples.manners.Chosen;
+import org.drools.examples.manners.Context;
+import org.drools.examples.manners.Count;
+import org.drools.examples.manners.Guest;
+import org.drools.examples.manners.LastSeat;
+import org.drools.examples.manners.Path;
+import org.drools.examples.manners.Seating;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.InvalidRuleException;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Not;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.MockField;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class HashedTableComponentTest extends DroolsTestCase {
+
+ protected Package pkg;
+
+
+ private ClassObjectType pathType;
+
+
+ private Evaluator objectEqualEvaluator;
+
+ private Evaluator integerEqualEvaluator;
+
+ private Path p1Alex;
+
+ private Path p2John;
+
+ private Path p3Mike;
+
+ private Path p4Alex;
+
+ private Path p5Alex;
+
+ protected void setUp() throws Exception {
+
+ this.p1Alex = new Path( 1, 1, "Alex" );
+ this.p2John = new Path( 2, 1, "John" );
+ this.p3Mike = new Path( 3, 1, "Mike" );
+ this.p4Alex = new Path( 4, 1, "Alex" );
+ this.p5Alex = new Path( 1, 4, "Alex" );
+ this.pathType = new ClassObjectType( Path.class );
+
+ this.integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+ this.objectEqualEvaluator = ValueType.OBJECT_TYPE.getEvaluator( Operator.EQUAL );
+
+ this.pkg = new Package( "Miss Manners for Hashed Table Component" );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testHashedTableComponentNoAlpha() throws Exception {
+
+ Rule r = this.getMakePathNoAlpha( );
+ this.pkg.addRule( r );
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ ruleBase.addPackage( this.pkg );
+ final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory( );
+ wm.assertObject( this.p1Alex );
+ wm.assertObject( this.p2John );
+ wm.assertObject( this.p3Mike );
+ wm.assertObject( this.p4Alex );
+ wm.assertObject( this.p5Alex );
+
+ Iterator it;
+ Tuple tuple;
+ FactTable ft = wm.getFactTable( Path.class );
+ ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints( )
+ .next( );
+ LeapsFactHandle[] fh = new LeapsFactHandle[1];
+ fh[0] = new LeapsFactHandle( 99, p1Alex );
+ tuple = new LeapsTuple( fh, null, null );
+
+ it = ft.reverseOrderIterator( tuple, notConstraint );
+ assertSame( "Expected matching",
+ ( (LeapsFactHandle) it.next( ) ).getObject( ),
+ p1Alex );
+ assertSame( "Expected matching",
+ ( (LeapsFactHandle) it.next( ) ).getObject( ),
+ p5Alex );
+ assertFalse( "Did not expect any more data", it.hasNext( ) );
+
+ fh[0] = new LeapsFactHandle( 99, p3Mike );
+ tuple = new LeapsTuple( fh, null, null );
+
+ it = ft.reverseOrderIterator( tuple, notConstraint );
+ assertSame( "Expected matching",
+ ( (LeapsFactHandle) it.next( ) ).getObject( ),
+ p3Mike );
+ assertFalse( "Did not expect any more data", it.hasNext( ) );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testHashedTableComponentAlpha() throws Exception {
+
+ Rule r = this.getMakePathAlpha( );
+ this.pkg.addRule( r );
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ ruleBase.addPackage( this.pkg );
+ final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory( );
+
+ wm.assertObject( this.p1Alex );
+ wm.assertObject( this.p2John );
+ wm.assertObject( this.p3Mike );
+ wm.assertObject( this.p4Alex );
+ wm.assertObject( this.p5Alex );
+
+ Iterator it;
+ Tuple tuple;
+ FactTable ft = wm.getFactTable( Path.class );
+ ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints( )
+ .next( );
+ LeapsFactHandle[] fh = new LeapsFactHandle[1];
+ fh[0] = new LeapsFactHandle( 99, p1Alex );
+ tuple = new LeapsTuple( fh, null, null );
+
+ it = ft.reverseOrderIterator( tuple, notConstraint );
+ assertFalse( "Did not expect any more data", it.hasNext( ) );
+
+ fh[0] = new LeapsFactHandle( 99, p3Mike );
+ tuple = new LeapsTuple( fh, null, null );
+
+ it = ft.reverseOrderIterator( tuple, notConstraint );
+ assertSame( "Expected matching",
+ ( (LeapsFactHandle) it.next( ) ).getObject( ),
+ p3Mike );
+ assertFalse( "Did not expect any more data", it.hasNext( ) );
+ }
+
+ /**
+ * <pre>
+ * rule makePath() {
+ * int pathId;
+ * String pathGuestName;
+ *
+ * when {
+ * Path( pathId:id, pathGuestName:guest )
+ * (not Path( id == pathId, guestName == pathGuestName )
+ * } then {
+ * nothing;
+ *
+ * }
+ * }
+ * </pre>
+ *
+ * @return
+ * @throws IntrospectionException
+ * @throws InvalidRuleException
+ */
+ private Rule getMakePathAlpha() throws IntrospectionException, InvalidRuleException {
+ final Rule rule = new Rule( "makePathNoAlpha" );
+ // -----------
+ // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+ // -----------
+ final Column pathColumn = new Column( 0, this.pathType );
+ setFieldDeclaration( pathColumn, "id", "pathId" );
+
+ setFieldDeclaration( pathColumn, "guestName", "pathGuestName" );
+
+ rule.addPattern( pathColumn );
+
+ final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+ final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+ // -------------
+ // (not Path( id == seatingId, guestName == pathGuestName )
+ // -------------
+ final Column notPathColumn = new Column( 3, this.pathType );
+
+ notPathColumn.addConstraint( getLiteralConstraint( notPathColumn,
+ "guestName",
+ "Mike",
+ this.objectEqualEvaluator ) );
+
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "id",
+ pathIdDeclaration,
+ this.integerEqualEvaluator ) );
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "guestName",
+ pathGuestNameDeclaration,
+ this.objectEqualEvaluator ) );
+
+ final Not not = new Not( );
+
+ not.addChild( notPathColumn );
+
+ rule.addPattern( not );
+
+ // ------------
+ // drools.assert( new Path( id, pathName, pathSeat ) );
+ // ------------
+ final Consequence consequence = new Consequence( ) {
+
+ public void evaluate( KnowledgeHelper drools, WorkingMemory workingMemory )
+ throws ConsequenceException {
+ // empty
+ }
+ };
+
+ rule.setConsequence( consequence );
+
+ return rule;
+ }
+
+ /**
+ * <pre>
+ * rule makePath() {
+ * int pathId;
+ * String pathGuestName;
+ *
+ * when {
+ * Path( pathId:id, pathGuestName:guest )
+ * (not Path( id == pathId, guestName == pathGuestName )
+ * } then {
+ * nothing;
+ *
+ * }
+ * }
+ * </pre>
+ *
+ * @return
+ * @throws IntrospectionException
+ * @throws InvalidRuleException
+ */
+ private Rule getMakePathNoAlpha() throws IntrospectionException, InvalidRuleException {
+ final Rule rule = new Rule( "makePathNoAlpha" );
+ // -----------
+ // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+ // -----------
+ final Column pathColumn = new Column( 0, this.pathType );
+ setFieldDeclaration( pathColumn, "id", "pathId" );
+
+ setFieldDeclaration( pathColumn, "guestName", "pathGuestName" );
+
+ rule.addPattern( pathColumn );
+
+ final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+ final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+ // -------------
+ // (not Path( id == seatingId, guestName == pathGuestName )
+ // -------------
+ final Column notPathColumn = new Column( 3, this.pathType );
+
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "id",
+ pathIdDeclaration,
+ this.integerEqualEvaluator ) );
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "guestName",
+ pathGuestNameDeclaration,
+ this.objectEqualEvaluator ) );
+
+ final Not not = new Not( );
+
+ not.addChild( notPathColumn );
+
+ rule.addPattern( not );
+
+ // ------------
+ // drools.assert( new Path( id, pathName, pathSeat ) );
+ // ------------
+ final Consequence consequence = new Consequence( ) {
+
+ public void evaluate( KnowledgeHelper drools, WorkingMemory workingMemory )
+ throws ConsequenceException {
+ // empty
+ }
+ };
+
+ rule.setConsequence( consequence );
+
+ return rule;
+ }
+
+ public static int getIndex( final Class clazz, final String name )
+ throws IntrospectionException {
+ final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz )
+ .getPropertyDescriptors( );
+ for (int i = 0; i < descriptors.length; i++) {
+ if (descriptors[i].getName( ).equals( name )) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private FieldConstraint getLiteralConstraint( final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator )
+ throws IntrospectionException {
+ final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+ final FieldValue field = new MockField( fieldValue );
+
+ return new LiteralConstraint( extractor, evaluator, field );
+ }
+
+ private void setFieldDeclaration( final Column column,
+ final String fieldName,
+ final String identifier )
+ throws IntrospectionException {
+ final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+ column.addDeclaration( identifier, extractor );
+ }
+
+ private FieldConstraint getBoundVariableConstraint( final Column column,
+ final String fieldName,
+ final Declaration declaration,
+ final Evaluator evaluator )
+ throws IntrospectionException {
+ final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+ return new VariableConstraint( extractor, declaration, evaluator );
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -71,7 +71,7 @@
new ArrayList(),
new ArrayList(),
new ArrayList(),
- new ArrayList() );
+ new ArrayList() );
final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
PropagationContext context1;
@@ -130,7 +130,7 @@
final LeapsRule leapsRule1 = new LeapsRule( rule1,
new ArrayList(),
new ArrayList(),
- new ArrayList(),
+ new ArrayList(),
new ArrayList() );
final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
@@ -225,7 +225,7 @@
final LeapsRule leapsRule1 = new LeapsRule( rule1,
new ArrayList(),
new ArrayList(),
- new ArrayList(),
+ new ArrayList(),
new ArrayList() );
final LeapsFactHandle tuple1FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
@@ -298,7 +298,7 @@
final LeapsRule leapsRule1 = new LeapsRule( rule1,
new ArrayList(),
new ArrayList(),
- new ArrayList(),
+ new ArrayList(),
new ArrayList() );
final LeapsFactHandle tuple1Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java 2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java 2006-08-19 05:27:40 UTC (rev 5945)
@@ -78,7 +78,7 @@
final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
factHandlesTuple[0] = tupleFactHandle;
- final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
(LeapsRule) leapsRules.get( 0 ),
context );
@@ -137,7 +137,7 @@
final LeapsFactHandle tupleFactHandleIn = (LeapsFactHandle) workingMemory.assertObject( "tuple object in" );
final LeapsFactHandle[] factHandlesTupleIn = new LeapsFactHandle[1];
factHandlesTupleIn[0] = tupleFactHandleIn;
- final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
final LeapsTuple tupleIn = new LeapsTuple( factHandlesTupleIn,
(LeapsRule) leapsRules.get( 0 ),
context2 );
@@ -156,7 +156,7 @@
final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
factHandlesTuple[0] = tupleFactHandle;
- final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
(LeapsRule) leapsRules.get( 0 ),
context );
More information about the jboss-svn-commits
mailing list