[jboss-svn-commits] JBL Code SVN: r6972 - in labs/jbossrules/trunk: . drools-leaps drools-leaps/src drools-leaps/src/main drools-leaps/src/main/java drools-leaps/src/main/java/org drools-leaps/src/main/java/org/drools drools-leaps/src/main/java/org/drools/leaps drools-leaps/src/main/java/org/drools/leaps/conflict drools-leaps/src/main/java/org/drools/leaps/util drools-leaps/src/test drools-leaps/src/test/java drools-leaps/src/test/java/org drools-leaps/src/test/java/org/drools drools-leaps/src/test/java/org/drools/leaps drools-leaps/src/test/java/org/drools/leaps/util

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Oct 20 13:34:16 EDT 2006


Author: mark.proctor at jboss.com
Date: 2006-10-20 13:34:03 -0400 (Fri, 20 Oct 2006)
New Revision: 6972

Added:
   labs/jbossrules/trunk/drools-leaps/
   labs/jbossrules/trunk/drools-leaps/src/
   labs/jbossrules/trunk/drools-leaps/src/main/
   labs/jbossrules/trunk/drools-leaps/src/main/java/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java
   labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java
   labs/jbossrules/trunk/drools-leaps/src/test/
   labs/jbossrules/trunk/drools-leaps/src/test/java/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/conflict/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java
   labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java
Log:
JBRULES-531 move LEAPS to its own module
-Leaps is now in its own module, but still need to hook  it into the main build system.

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,35 @@
+package org.drools.leaps;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Tuple;
+
+class AlphaMemory {
+    private final IdentityMap alphaChecks = new IdentityMap();
+
+    AlphaMemory() {
+
+    }
+
+    boolean checkAlpha(final AlphaNodeFieldConstraint alpha,
+                       final InternalFactHandle factHandle,
+                       final Tuple tuple,
+                       final WorkingMemory workingMemory) {
+        Boolean ret = (Boolean) this.alphaChecks.get( factHandle );
+        if ( ret == null ) {
+            ret = new Boolean( alpha.isAllowed( factHandle.getObject(),
+                                                tuple,
+                                                workingMemory ) );
+            this.alphaChecks.put( factHandle,
+                                  ret );
+        }
+
+        return ret.booleanValue();
+    }
+
+    boolean isAlphaBeenChecked(final InternalFactHandle factHandle) {
+        return this.alphaChecks != null && this.alphaChecks.containsKey( factHandle );
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,234 @@
+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.common.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+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.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Not;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * 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 Builder {
+    /**
+     * 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 = Builder.processColumn( (Column) object,
+                                                         true );
+                    // create column constraints
+                } else {
+                    // NOTS and EXISTS
+                    GroupElement ce = (GroupElement) object;
+                    while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
+                        ce = (GroupElement) ce.getChildren().get( 0 );
+                    }
+                    constraints = Builder.processColumn( (Column) ce.getChildren().get( 0 ),
+                                                         false );
+                }
+                if ( object instanceof Not ) {
+                    notCols.add( constraints );
+                } else if ( object instanceof Exists ) {
+                    existsCols.add( 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,
+                                                         final boolean removeIdentities) {
+        BetaConstraints binder;
+        final List alphaConstraints = new ArrayList();
+        final List predicateConstraints = new ArrayList();
+
+        final List constraints = column.getConstraints();
+
+        final 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 AlphaNodeFieldConstraint fieldConstraint = (AlphaNodeFieldConstraint) object;
+            if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+                alphaConstraints.add( fieldConstraint );
+            } else {
+                predicateConstraints.add( fieldConstraint );
+            }
+        }
+
+        if ( !predicateConstraints.isEmpty() ) {
+            binder = new DefaultBetaConstraints( (AlphaNodeFieldConstraint[]) predicateConstraints.toArray( new AlphaNodeFieldConstraint[predicateConstraints.size()] ) );
+        } else {
+            binder = new DefaultBetaConstraints();
+        }
+
+        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 );
+        }
+
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,123 @@
+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.io.Serializable;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Column;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Tuple;
+
+/**
+ * Collection of <code>Column</code> specific constraints
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class ColumnConstraints
+    implements
+    Serializable {
+    private Object                           classType;
+
+    private final AlphaNodeFieldConstraint[] alphaConstraints;
+
+    private final boolean                    alphaPresent;
+
+    private final BetaConstraints            beta;
+
+    private final boolean                    betaPresent;
+
+    public ColumnConstraints(final Column column,
+                             final List alpha,
+                             final BetaConstraints beta) {
+        this.classType = LeapsBuilder.getLeapsClassType( column.getObjectType() );
+
+        if ( beta != null ) {
+            this.beta = beta;
+            this.betaPresent = true;
+        } else {
+            this.beta = null;
+            this.betaPresent = false;
+        }
+        if ( alpha != null && alpha.size() > 0 ) {
+            this.alphaConstraints = (AlphaNodeFieldConstraint[]) alpha.toArray( new AlphaNodeFieldConstraint[0] );
+            this.alphaPresent = true;
+        } else {
+            this.alphaConstraints = null;
+            this.alphaPresent = false;
+        }
+    }
+
+    protected final Object getClassType() {
+        return this.classType;
+    }
+
+    protected final boolean isAllowed(final InternalFactHandle factHandle,
+                                      final Tuple tuple,
+                                      final WorkingMemory workingMemory) {
+        return this.isAllowedAlpha( factHandle,
+                                    tuple,
+                                    workingMemory ) && this.isAllowedBeta( factHandle,
+                                                                           tuple,
+                                                                           workingMemory );
+    }
+
+    public final boolean isAllowedAlpha(final InternalFactHandle factHandle,
+                                        final Tuple tuple,
+                                        final WorkingMemory workingMemory) {
+        if ( this.alphaPresent ) {
+            for ( int i = 0, length = this.alphaConstraints.length; i < length; i++ ) {
+                // escape immediately if some condition does not match
+                if ( !this.alphaConstraints[i].isAllowed( factHandle.getObject(),
+                                                          tuple,
+                                                          workingMemory ) ) {
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    protected final boolean isAllowedBeta(final InternalFactHandle factHandle,
+                                          final Tuple tuple,
+                                          final WorkingMemory workingMemory) {
+        if ( this.betaPresent ) {
+            return this.beta.isAllowed( factHandle,
+                                        tuple,
+                                        workingMemory );
+        }
+
+        return true;
+    }
+
+    protected final boolean isAlphaPresent() {
+        return this.alphaPresent;
+    }
+
+    protected AlphaNodeFieldConstraint[] getAlphaContraints() {
+        return this.alphaConstraints;
+    }
+
+    protected AlphaNodeFieldConstraint[] getBetaContraints() {
+        return this.beta.getConstraints();
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,35 @@
+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.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Leaps specific conflict resolver provides for separate fact and rule based
+ * conflict resolution
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public interface ConflictResolver
+    extends
+    Serializable {
+    public Comparator getFactConflictResolver();
+
+    public Comparator getRuleConflictResolver();
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,60 @@
+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.
+ */
+
+/**
+ * To store all references needed to retract a fact
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.WorkingMemory
+ * @see java.beans.PropertyChangeListener
+ * @see java.io.Serializable
+ * 
+ */
+
+class FactHandleTupleAssembly {
+    final LeapsTuple        tuple;
+
+    final int               index;
+
+    final int               type;
+
+    public final static int EXISTS = 1;
+
+    public final static int NOT    = 2;
+
+    FactHandleTupleAssembly(final int type,
+                            final LeapsTuple tuple,
+                            final int index) {
+        this.type = type;
+        this.tuple = tuple;
+        this.index = index;
+    }
+
+    protected int getIndex() {
+        return this.index;
+    }
+
+    protected LeapsTuple getTuple() {
+        return this.tuple;
+    }
+
+    public int getType() {
+        return this.type;
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,262 @@
+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.Comparator;
+import java.util.Iterator;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * Implementation of a container to store data elements used throughout the
+ * leaps. Stores fact handles and companion information - relevant rules
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+class FactTable extends Table {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 5964698708240814905L;
+
+    /**
+     * positive rules are not complete rules but rather its conditions that
+     * relates by type
+     */
+    private final RuleTable   rules;
+
+    /**
+     * dynamic rule management support. used to push facts on stack again after
+     * fireAllRules by working memory and adding of a new rule after that
+     */
+    private boolean           reseededStack    = false;
+
+    /**
+     * Tuples that are either already on agenda or are very close (missing
+     * exists or have not facts matching)
+     */
+    private final IdentityMap tuples;
+
+    /**
+     * initializes base LeapsTable with appropriate Comparator and positive and
+     * negative rules repositories
+     * 
+     * @param factConflictResolver
+     * @param ruleConflictResolver
+     */
+    public FactTable(final ConflictResolver conflictResolver) {
+        super( conflictResolver.getFactConflictResolver() );
+        this.rules = new RuleTable( conflictResolver.getRuleConflictResolver() );
+        this.tuples = new IdentityMap();
+        this.comparator = conflictResolver.getFactConflictResolver();
+        this.notAndExistsHashedTables = new IdentityMap();
+    }
+
+    /**
+     * Add rule
+     * 
+     * @param workingMemory
+     * @param ruleHandle
+     */
+    public void addRule(final LeapsWorkingMemory workingMemory,
+                        final LeapsRuleHandle ruleHandle) {
+        if ( !this.rules.contains( ruleHandle ) ) {
+            this.rules.add( ruleHandle );
+            // push facts back to stack if needed
+            this.checkAndAddFactsToStack( workingMemory );
+        }
+    }
+
+    /**
+     * Remove rule
+     * 
+     * @param ruleHandle
+     */
+    public void removeRule(final LeapsWorkingMemory workingMemory,
+                           final LeapsRuleHandle ruleHandle) {
+        this.rules.remove( ruleHandle );
+        // remove tuples that are still there
+        for ( final Iterator it = this.getTuplesIterator(); it.hasNext(); ) {
+            final LeapsTuple tuple = (LeapsTuple) it.next();
+            if ( ruleHandle.getLeapsRule().getRule() == tuple.getLeapsRule().getRule() ) {
+                this.tuples.remove( tuple );
+            }
+        }
+    }
+
+    /**
+     * checks if rule arrived after working memory fireAll event and if no rules
+     * where added since then. Iterates through all facts asserted (and not
+     * retracted, they are not here duh) and adds them to the stack.
+     * 
+     * @param working
+     *            memory
+     * 
+     */
+    private void checkAndAddFactsToStack(final LeapsWorkingMemory workingMemory) {
+        if ( this.reseededStack ) {
+            this.setReseededStack( false );
+
+            final PropagationContextImpl context = new PropagationContextImpl( workingMemory.nextPropagationIdCounter(),
+                                                                               PropagationContext.ASSERTION,
+                                                                               null,
+                                                                               null );
+
+            // let's only add facts below waterline - added before rule is added
+            // rest would be added to stack automatically
+            final DefaultFactHandle startFactHandle = new DefaultFactHandle( workingMemory.getIdLastFireAllAt(),
+                                                                             new Object() );
+            for ( final Iterator it = this.iteratorFromPositionToTableStart( startFactHandle,
+                                                                             startFactHandle ); it.hasNext(); ) {
+                final LeapsFactHandle handle = (LeapsFactHandle) it.next();
+                workingMemory.pushTokenOnStack( handle,
+                                                new Token( workingMemory,
+                                                           handle,
+                                                           context ) );
+            }
+        }
+    }
+
+    /**
+     * set indicator if rule was added already after fire all completed
+     * 
+     * @param new
+     *            value
+     */
+    public void setReseededStack(final boolean reseeded) {
+        this.reseededStack = reseeded;
+    }
+
+    /**
+     * returns an iterator of rule handles to the regular(positive) CEs portions
+     * of rules were type matches this fact table underlying type
+     * 
+     * @return iterator of positive rule handles
+     */
+    public Iterator getRulesIterator() {
+        return this.rules.iterator();
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public String toString() {
+        final StringBuffer ret = new StringBuffer();
+
+        for ( final Iterator it = this.iterator(); it.hasNext(); ) {
+            final LeapsFactHandle handle = (LeapsFactHandle) it.next();
+            ret.append( "\n" + handle + "[" + handle.getObject() + "]" );
+        }
+
+        ret.append( "\nTuples :" );
+
+        for ( final Iterator it = this.tuples.values().iterator(); it.hasNext(); ) {
+            ret.append( "\n" + it.next() );
+        }
+
+        ret.append( "\nRules :" );
+
+        for ( final Iterator it = this.rules.iterator(); it.hasNext(); ) {
+            final LeapsRuleHandle handle = (LeapsRuleHandle) it.next();
+            ret.append( "\n\t" + handle.getLeapsRule().getRule().getName() + "[dominant - " + handle.getDominantPosition() + "]" );
+        }
+
+        return ret.toString();
+    }
+
+    protected Iterator getTuplesIterator() {
+        return this.tuples.values().iterator();
+    }
+
+    protected void addTuple(final LeapsTuple 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(final Object object) {
+        super.add( object );
+        for ( final Iterator it = this.notAndExistsHashedTables.values().iterator(); it.hasNext(); ) {
+            // this will also add link to hash into the leapsfacthandle
+            ((HashedTableComponent) it.next()).add( (LeapsFactHandle) object );
+        }
+    }
+
+    public void remove(final Object object) {
+        super.remove( object );
+        // during modify we need to directly remove facts from participating 
+        // hashes because modify can throw us off
+        ((LeapsFactHandle) object).removeFromHash();
+    }
+
+    protected void createHashedSubTable(final ColumnConstraints constraint) {
+        this.notAndExistsHashedTables.put( constraint,
+                                           new HashedTableComponent( constraint,
+                                                                     this.comparator ) );
+    }
+
+    protected TableIterator reverseOrderIterator(final Tuple tuple,
+                                                 final ColumnConstraints constraint) {
+        TableIterator ret = ((HashedTableComponent) this.notAndExistsHashedTables.get( constraint )).reverseOrderIterator( tuple );
+        if ( ret == null ) {
+            ret = Table.emptyIterator();
+        }
+        return ret;
+    }
+
+    protected TableIterator iteratorFromPositionToTableStart(final Tuple tuple,
+                                                             final ColumnConstraints constraint,
+                                                             final LeapsFactHandle startFactHandle,
+                                                             final LeapsFactHandle currentFactHandle) {
+        TableIterator ret = ((HashedTableComponent) this.notAndExistsHashedTables.get( constraint )).iteratorFromPositionToTableStart( tuple,
+                                                                                                                                       startFactHandle,
+                                                                                                                                       currentFactHandle );
+        if ( ret == null ) {
+            ret = Table.emptyIterator();
+        }
+        return ret;
+    }
+
+    protected TableIterator iteratorFromPositionToTableEnd(final Tuple tuple,
+                                                           final ColumnConstraints constraint,
+                                                           final 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-leaps/src/main/java/org/drools/leaps/FromConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,24 @@
+package org.drools.leaps;
+
+import java.util.Arrays;
+
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.rule.Column;
+import org.drools.spi.DataProvider;
+
+public class FromConstraint extends ColumnConstraints {
+    private final DataProvider provider;
+
+    public FromConstraint(final Column column,
+                          final DataProvider provider,
+                          final ColumnConstraints constraints) {
+        super( column,
+               (constraints.getAlphaContraints() == null || constraints.getAlphaContraints().length == 0) ? Arrays.asList( new FromConstraint[0] ) : Arrays.asList( constraints.getAlphaContraints() ),
+               new DefaultBetaConstraints( constraints.getBetaContraints() ) );
+        this.provider = provider;
+    }
+
+    public DataProvider getProvider() {
+        return this.provider;
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,147 @@
+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(final ColumnConstraints constraints,
+                                final 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(final LeapsFactHandle factHandle) {
+        final Table table = this.getTable( factHandle );
+        if ( table != null ) {
+            table.add( factHandle );
+            factHandle.addHash( table );
+        }
+    }
+
+    public TableIterator reverseOrderIterator(final Tuple tuple) {
+        final Table table = this.getTable( tuple );
+        if ( table != null ) {
+            return table.reverseOrderIterator();
+        } else {
+            return null;
+        }
+    }
+
+    public TableIterator iteratorFromPositionToTableEnd(final Tuple tuple,
+                                                        final LeapsFactHandle startFactHandle) {
+        final Table table = this.getTable( tuple );
+        if ( table != null ) {
+            return table.iteratorFromPositionToTableEnd( startFactHandle );
+        } else {
+            return null;
+        }
+    }
+
+    public TableIterator iteratorFromPositionToTableStart(final Tuple tuple,
+                                                          final LeapsFactHandle startFactHandle,
+                                                          final LeapsFactHandle currentFactHandle) {
+        final Table table = this.getTable( tuple );
+        if ( table != null ) {
+            return table.iteratorFromPositionToTableStart( startFactHandle,
+                                                           currentFactHandle );
+        } else {
+            return null;
+        }
+    }
+
+    private Table getTable(final 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 = HashedTableComponent.DEFAULT_HASH;
+                if ( this.constraints.getBetaContraints()[i] instanceof VariableConstraint && ((VariableConstraint) this.constraints.getBetaContraints()[i]).getEvaluator().getOperator() == Operator.EQUAL ) {
+                    final 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(final LeapsFactHandle factHandle) {
+        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; i++ ) {
+                    Integer hash = HashedTableComponent.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 ) {
+                            map = new HashMap();
+                            currentMap.put( hash,
+                                            map );
+                        }
+                        currentMap = map;
+                    } else {
+                        Table table = (Table) currentMap.get( hash );
+                        if ( table == null ) {
+                            table = new Table( this.comparator );
+                            currentMap.put( hash,
+                                            table );
+                        }
+                        ret = table;
+                    }
+                }
+            } else {
+                return this.noConstraintsTable;
+            }
+        }
+        return ret;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,67 @@
+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.List;
+
+import org.drools.common.DefaultAgenda;
+import org.drools.rule.Query;
+import org.drools.spi.Activation;
+import org.drools.spi.ConsequenceException;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class LeapsAgenda extends DefaultAgenda {
+    /**
+     * 
+     */
+    private static final long  serialVersionUID = 7985611305408622557L;
+
+    private LeapsWorkingMemory workingMemory;
+
+    public LeapsAgenda(final LeapsWorkingMemory workingMemory) {
+        super( workingMemory );
+        this.workingMemory = workingMemory;
+    }
+
+    public synchronized void fireActivation(final Activation activation) throws ConsequenceException {
+        if ( activation.getRule() instanceof Query ) {
+            // put query results to the working memory location
+            this.workingMemory.addToQueryResults( activation.getRule().getName(),
+                                                  activation.getTuple() );
+        } else {
+            // fire regular rule
+            super.fireActivation( activation );
+            ((LeapsTuple) activation.getTuple()).setWasFired( true );
+        }
+    }
+
+    /**
+     * to accomodate the difference between rete and leaps in storing
+     * activations. we pull activations from rule to activations map we store in
+     * working memory to facilitate activations removal when rule is removed
+     * from the memory
+     * 
+     */
+    public Activation[] getActivations() {
+        final List list = this.workingMemory.getActivations();
+        return (Activation[]) list.toArray( new Activation[list.size()] );
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -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.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+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.AlphaNodeFieldConstraint;
+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) {
+        BetaConstraints binder;
+        final List alphaConstraints = new ArrayList();
+        final List predicateConstraints = new ArrayList();
+
+        final List constraints = column.getConstraints();
+
+        final 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 AlphaNodeFieldConstraint fieldConstraint = (AlphaNodeFieldConstraint) object;
+            if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+                alphaConstraints.add( fieldConstraint );
+            } else {
+                predicateConstraints.add( fieldConstraint );
+            }
+        }
+
+        if ( !predicateConstraints.isEmpty() ) {
+            binder = new DefaultBetaConstraints( (AlphaNodeFieldConstraint[]) predicateConstraints.toArray( new AlphaNodeFieldConstraint[predicateConstraints.size()] ) );
+        } else {
+            binder = new DefaultBetaConstraints();
+        }
+
+        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(final 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(final 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

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,123 @@
+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.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.leaps.util.Table;
+
+/**
+ * class container for each object asserted / retracted into the system
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class LeapsFactHandle extends DefaultFactHandle {
+
+    private List activatedTuples = null;
+
+    private List notTuples       = null;
+
+    private List existsTuples    = null;
+
+    public LeapsFactHandle(final long id,
+                           final Object object) {
+        super( id,
+               object );
+    }
+
+    protected void addActivatedTuple(final LeapsTuple tuple) {
+        if ( this.activatedTuples == null ) {
+            this.activatedTuples = new LinkedList();
+        }
+        this.activatedTuples.add( tuple );
+    }
+
+    protected void addNotTuple(final LeapsTuple tuple,
+                               final int index) {
+        if ( this.notTuples == null ) {
+            this.notTuples = new LinkedList();
+        }
+        this.notTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.NOT,
+                                                         tuple,
+                                                         index ) );
+    }
+
+    protected void addExistsTuple(final LeapsTuple tuple,
+                                  final int index) {
+        if ( this.existsTuples == null ) {
+            this.existsTuples = new LinkedList();
+        }
+        this.existsTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.EXISTS,
+                                                            tuple,
+                                                            index ) );
+    }
+
+    protected Iterator getActivatedTuples() {
+        if ( this.activatedTuples != null ) {
+            return this.activatedTuples.iterator();
+        }
+        return null;
+    }
+
+    protected Iterator getNotTupleAssemblies() {
+        if ( this.notTuples != null ) {
+            return this.notTuples.iterator();
+        }
+        return null;
+    }
+
+    protected Iterator getExistsTupleAssemblies() {
+        if ( this.existsTuples != null ) {
+            return this.existsTuples.iterator();
+        }
+        return null;
+    }
+
+    protected void clearActivatedTuples() {
+        this.activatedTuples = null;
+    }
+
+    protected void clearExistsTuples() {
+        this.existsTuples = null;
+    }
+
+    protected void clearNotTuples() {
+        this.notTuples = null;
+    }
+
+    private LinkedList hashes = null;
+
+    protected void addHash(final Table table) {
+        if ( this.hashes == null ) {
+            this.hashes = new LinkedList();
+        }
+        this.hashes.add( table );
+    }
+
+    protected void removeFromHash() {
+        if ( this.hashes != null ) {
+            for ( final Iterator it = this.hashes.iterator(); it.hasNext(); ) {
+                ((Table) it.next()).remove( this );
+            }
+            this.hashes.clear();
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,97 @@
+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 org.drools.common.EqualityKey;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.FactHandleFactory;
+
+/**
+ * @author Alexander Bagerman
+ * 
+ */
+class LeapsFactHandleFactory
+    implements
+    FactHandleFactory {
+    private static final long serialVersionUID = 8510623248591449450L;
+
+    private long              counter;
+
+    protected LeapsFactHandleFactory() {
+        this.counter = 0L;
+    }
+
+    /**
+     * it does not make sense in leaps context. so we generate fact handle as we
+     * did with no counter supplied
+     * 
+     * @see org.drools.reteoo.FactHandleFactory
+     */
+    public final InternalFactHandle newFactHandle(final Object object) {
+        return new LeapsFactHandle( this.getNextId(),
+                                    object );
+    }
+
+    /**
+     * leaps handle 
+     * 
+     * @param object
+     * @return leaps handle
+     */
+    public final InternalFactHandle newFactHandle(final long newId,
+                                                  final Object object) {
+        return newFactHandle( object );
+    }
+
+    /**
+     * 
+     * @return incremented id
+     */
+    protected synchronized long getNextId() {
+        return ++this.counter;
+    }
+
+    /**
+     * the same as in rete
+     * 
+     * @see org.drools.reteoo.FactHandleFactory
+     */
+    public final void increaseFactHandleRecency(final InternalFactHandle factHandle) {
+        factHandle.setRecency( this.getNextId() );
+    }
+
+    /**
+     * instead of destroying we put EqualityKey back there 
+     * because of the nature of Leaps processing delayed actions
+     * 
+     * @see org.drools.reteoo.FactHandleFactory
+     */
+    public void destroyFactHandle(final InternalFactHandle factHandle) {
+        factHandle.setEqualityKey( new EqualityKey( factHandle ) );
+    }
+
+    /**
+     * @see org.drools.reteoo.FactHandleFactory
+     */
+    public FactHandleFactory newInstance() {
+        return new LeapsFactHandleFactory();
+    }
+
+    public Class getFactHandleType() {
+        return LeapsFactHandle.class;
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,62 @@
+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 org.drools.FactHandle;
+import org.drools.QueryResult;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.spi.Tuple;
+
+/** 
+ *  
+ * @author Alexander Bagerman
+ * 
+ */
+
+public class LeapsQueryResult extends QueryResult {
+    public LeapsQueryResult(final Tuple tuple,
+                            final WorkingMemory workingMemory,
+                            final QueryResults queryResults) {
+        super( tuple,
+               workingMemory,
+               queryResults );
+    }
+
+    public Object get(final int i) {
+        // adjust for the DroolsQuery object
+        return super.get( i - 1 );
+    }
+
+    public FactHandle[] getFactHandles() {
+        // Strip the DroolsQuery fact
+        final FactHandle[] src = super.tuple.getFactHandles();
+        final FactHandle[] dst = new FactHandle[src.length - 1];
+        System.arraycopy( src,
+                          0,
+                          dst,
+                          0,
+                          dst.length );
+        return dst;
+    }
+
+    public int size() {
+        // Adjust for the DroolsQuery object
+        return super.size() + 1;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,82 @@
+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.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.drools.QueryResult;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.rule.Query;
+import org.drools.spi.Tuple;
+
+/** 
+ *  
+ * @author Alexander Bagerman
+ * 
+ */
+
+public class LeapsQueryResults extends QueryResults {
+
+    public LeapsQueryResults(final List results,
+                             final Query query,
+                             final WorkingMemory workingMemory) {
+        super( results,
+               query,
+               workingMemory );
+    }
+
+    public QueryResult get(final int i) {
+        if ( i > this.results.size() ) {
+            throw new NoSuchElementException();
+        }
+        return new LeapsQueryResult( (Tuple) this.results.get( i ),
+                                     this.workingMemory,
+                                     this );
+    }
+
+    public Iterator iterator() {
+        return new QueryResultsIterator( this.results.iterator() );
+    }
+
+    class QueryResultsIterator
+        implements
+        Iterator {
+        private Iterator iterator;
+
+        public QueryResultsIterator(final Iterator iterator) {
+            this.iterator = iterator;
+        }
+
+        public boolean hasNext() {
+            return this.iterator.hasNext();
+        }
+
+        public Object next() {
+            return new LeapsQueryResult( (Tuple) this.iterator.next(),
+                                         LeapsQueryResults.this.workingMemory,
+                                         LeapsQueryResults.this );
+        }
+
+        public void remove() {
+            this.iterator.remove();
+        }
+
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,161 @@
+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.io.Serializable;
+import java.util.ArrayList;
+
+import org.drools.common.AgendaGroupImpl;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Rule;
+
+/**
+ * Wrapper class to drools generic rule to extract matching elements from it to
+ * use during leaps iterations.
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+class LeapsRule
+    implements
+    Serializable {
+    Rule                      rule;
+
+    final ColumnConstraints[] columnConstraints;
+
+    final ColumnConstraints[] notColumnConstraints;
+
+    final ColumnConstraints[] existsColumnConstraints;
+
+    final EvalCondition[]     evalConditions;
+
+    boolean                   notColumnsPresent;
+
+    boolean                   existsColumnsPresent;
+
+    boolean                   evalCoditionsPresent;
+
+    final Class[]             existsNotsClasses;
+
+    public LeapsRule(final Rule rule,
+                     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);
+
+        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() );
+            }
+        }
+
+        this.existsNotsClasses = (Class[]) classes.toArray( new Class[0] );
+    }
+
+    Rule getRule() {
+        return this.rule;
+    }
+
+    int getNumberOfColumns() {
+        return this.columnConstraints.length;
+    }
+
+    int getNumberOfNotColumns() {
+        return this.notColumnConstraints.length;
+    }
+
+    int getNumberOfExistsColumns() {
+        return this.existsColumnConstraints.length;
+    }
+
+    int getNumberOfEvalConditions() {
+        return this.evalConditions.length;
+    }
+
+    Object getColumnClassObjectTypeAtPosition(final int idx) {
+        return this.columnConstraints[idx].getClassType();
+    }
+
+    ColumnConstraints getColumnConstraintsAtPosition(final int idx) {
+        return this.columnConstraints[idx];
+    }
+
+    ColumnConstraints[] getNotColumnConstraints() {
+        return this.notColumnConstraints;
+    }
+
+    ColumnConstraints[] getExistsColumnConstraints() {
+        return this.existsColumnConstraints;
+    }
+
+    EvalCondition[] getEvalConditions() {
+        return this.evalConditions;
+    }
+
+    boolean containsNotColumns() {
+        return this.notColumnsPresent;
+    }
+
+    boolean containsExistsColumns() {
+        return this.existsColumnsPresent;
+    }
+
+    boolean containsEvalConditions() {
+        return this.evalCoditionsPresent;
+    }
+
+    public int hashCode() {
+        return this.rule.hashCode();
+    }
+
+    public boolean equals(final Object that) {
+        return this == that;
+    }
+
+    Class[] getExistsNotColumnsClasses() {
+        return this.existsNotsClasses;
+    }
+
+    /** 
+     * to simulate terminal node memory we introduce 
+     * TerminalNodeMemory type attributes here
+     * 
+     */
+    private AgendaGroupImpl agendaGroup;
+
+    public AgendaGroupImpl getAgendaGroup() {
+        return this.agendaGroup;
+    }
+
+    public void setAgendaGroup(final AgendaGroupImpl agendaGroup) {
+        this.agendaGroup = agendaGroup;
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,205 @@
+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.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.PackageIntegrationException;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.WorkingMemory;
+import org.drools.common.AbstractRuleBase;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Rule;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * This base class for the engine and analogous to Drool's RuleBase class. It
+ * has a similar interface adapted to the Leaps algorithm
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class LeapsRuleBase extends AbstractRuleBase {
+    private static final long serialVersionUID = 1487738104393155409L;
+
+    private Map               leapsRules;
+
+    /**
+     * Default constructor - for Externalizable. This should never be used by a user, as it 
+     * will result in an invalid state for the instance.
+     */
+    public LeapsRuleBase() {
+
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param rete
+     *            The rete network.
+     */
+    public LeapsRuleBase(final String id) {
+        this( id,
+              null,
+              new LeapsFactHandleFactory() );
+    }
+
+    /**
+     * Construct.
+     * 
+     * @param rete
+     *            The rete network.
+     * @param conflictResolver
+     *            The conflict resolver.
+     * @param factHandleFactory
+     *            The fact handle factory.
+     * @param pkgs
+     * @param applicationData
+     * @throws PackageIntegrationException
+     * @throws Exception
+     */
+    public LeapsRuleBase(final String id,
+                         final RuleBaseConfiguration config,
+                         final FactHandleFactory factHandleFactory) {
+        super( id,
+               config,
+               factHandleFactory );
+        this.leapsRules = new HashMap();
+    }
+
+    /**
+     * @see RuleBase
+     */
+    public WorkingMemory newWorkingMemory() {
+        return newWorkingMemory( true );
+    }
+
+    /**
+     * @see RuleBase
+     */
+    public WorkingMemory newWorkingMemory(final boolean keepReference) {
+        final LeapsWorkingMemory workingMemory = new LeapsWorkingMemory( this.workingMemoryCounter++,
+                                                                         this );
+        // add all rules added so far
+        for ( final Iterator it = this.leapsRules.values().iterator(); it.hasNext(); ) {
+            workingMemory.addLeapsRules( (List) it.next() );
+        }
+        //
+        super.addWorkingMemory( workingMemory,
+                                keepReference );
+
+        return workingMemory;
+    }
+
+    /**
+     * Creates leaps rule wrappers and propagate rule to the working memories
+     * 
+     * @param rule
+     * @throws FactException
+     * @throws InvalidPatternException
+     */
+    public void addRule(final Rule rule) throws FactException,
+                                        InvalidPatternException {
+        // checks rule validity
+        super.addRule( rule );
+
+        final List rules = LeapsBuilder.processRule( rule );
+
+        this.leapsRules.put( rule,
+                             rules );
+
+        for ( final Iterator it = this.getWorkingMemories().iterator(); it.hasNext(); ) {
+            ((LeapsWorkingMemory) it.next()).addLeapsRules( rules );
+        }
+
+        // Iterate each workingMemory and attempt to fire any rules, that were
+        // activated as a result of the new rule addition
+        // abstract rule base does it
+    }
+
+    public void removeRule(final Rule rule) {
+        for ( final Iterator it = this.getWorkingMemories().iterator(); it.hasNext(); ) {
+            ((LeapsWorkingMemory) it.next()).removeRule( (List) this.leapsRules.remove( rule ) );
+        }
+    }
+
+    /**
+     * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+     * 
+     */
+    public void writeExternal(final ObjectOutput stream) throws IOException {
+        doWriteExternal( stream,
+                         new Object[0] );
+    }
+
+    /**
+     * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+     * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
+     * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
+     * 
+     */
+    public void readExternal(final ObjectInput stream) throws IOException,
+                                                      ClassNotFoundException {
+        doReadExternal( stream,
+                        new Object[0] );
+
+        this.leapsRules = new HashMap();
+
+        for ( int i = 0; i < this.getPackages().length; i++ ) {
+            final Rule[] rules = this.getPackages()[i].getRules();
+
+            for ( int j = 0; j < rules.length; ++j ) {
+                addRule( rules[j] );
+            }
+        }
+    }
+
+    public void assertObject(final FactHandle handle,
+                             final Object object,
+                             final PropagationContext context,
+                             final ReteooWorkingMemory workingMemory) throws FactException {
+        // do nothing as reteoo specific
+
+    }
+
+    public void modifyObject(final FactHandle handle,
+                             final PropagationContext context,
+                             final ReteooWorkingMemory workingMemory) throws FactException {
+        // do nothing as reteoo specific
+
+    }
+
+    public void retractObject(final FactHandle handle,
+                              final PropagationContext context,
+                              final ReteooWorkingMemory workingMemory) throws FactException {
+        // do nothing as reteoo specific
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,86 @@
+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 org.drools.common.DefaultFactHandle;
+
+/**
+ * class container for rules. Re-using defaultfact handle 
+ * 
+ * class container for rules used in the system. Handle is created for each
+ * leaps rule, dominant position (column/ce position), dominant position type
+ * (class at the column/ce position) or indicator if handle is for asserted or
+ * retracted tuple combination
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class LeapsRuleHandle extends DefaultFactHandle {
+
+    // ce position for which handle is created
+    private final int dominantPosition;
+
+    public LeapsRuleHandle(final long id,
+                           final LeapsRule rule,
+                           final int dominantPosition) {
+        super( id,
+               rule );
+        this.dominantPosition = dominantPosition;
+    }
+
+    /**
+     * @return leaps wrapped rule
+     */
+    public LeapsRule getLeapsRule() {
+        return (LeapsRule) this.getObject();
+    }
+
+    /**
+     * @return base column / ce position
+     */
+    public int getDominantPosition() {
+        return this.dominantPosition;
+    }
+
+    /**
+     * @see org.drools.rule.Rule
+     */
+    public int getRuleComplexity() {
+        return this.getLeapsRule().getRule().getDeclarations().length;
+    }
+
+    /**
+     * @see org.drools.rule.Rule
+     */
+    public int getSalience() {
+        return this.getLeapsRule().getRule().getSalience();
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public boolean equals(final Object that) {
+        return super.equals( that ) && (this.getDominantPosition() == ((LeapsRuleHandle) that).getDominantPosition());
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public String toString() {
+        return "R-" + this.getId() + " \"" + this.getLeapsRule().toString() + "\" [pos - " + this.dominantPosition + "]";
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,285 @@
+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.io.Serializable;
+
+import org.drools.FactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * Leaps Tuple implementation
+ * 
+ * @author Alexander Bagerman
+ */
+class LeapsTuple
+    implements
+    Tuple,
+    Serializable {
+    private static final long       serialVersionUID       = 1L;
+
+    private PropagationContext      context;
+
+    private boolean                 readyForActivation;
+
+    private final LeapsFactHandle[] factHandles;
+
+    private LeapsFactHandle[]       blockingNotFactHandles = null;
+
+    private LeapsFactHandle[]       existsFactHandles      = null;
+
+    private Activation              activation;
+
+    private final LeapsRule         leapsRule;
+
+    private boolean                 wasFired               = false;
+
+    /**
+     * agendaItem parts
+     */
+    LeapsTuple(final LeapsFactHandle factHandles[],
+               final LeapsRule leapsRule,
+               final PropagationContext context) {
+        this.factHandles = factHandles;
+        this.leapsRule = leapsRule;
+        this.context = context;
+
+        if ( this.leapsRule != null ) {
+            if ( this.leapsRule.containsNotColumns() ) {
+                this.blockingNotFactHandles = new LeapsFactHandle[this.leapsRule.getNotColumnConstraints().length];
+                for ( int i = 0; i < this.blockingNotFactHandles.length; i++ ) {
+                    this.blockingNotFactHandles[i] = null;
+                }
+            }
+            if ( this.leapsRule.containsExistsColumns() ) {
+                this.existsFactHandles = new LeapsFactHandle[this.leapsRule.getExistsColumnConstraints().length];
+                for ( int i = 0; i < this.existsFactHandles.length; i++ ) {
+                    this.existsFactHandles[i] = null;
+                }
+            }
+        }
+        this.readyForActivation = (this.leapsRule == null || !this.leapsRule.containsExistsColumns());
+    }
+
+    /**
+     * get rule that caused this tuple to be generated
+     * 
+     * @return rule
+     */
+    protected LeapsRule getLeapsRule() {
+        return this.leapsRule;
+    }
+
+    /**
+     * Determine if this tuple depends upon a specified object.
+     * 
+     * @param handle
+     *            The object handle to test.
+     * 
+     * @return <code>true</code> if this tuple depends upon the specified
+     *         object, otherwise <code>false</code>.
+     * 
+     * @see org.drools.spi.Tuple
+     */
+    public boolean dependsOn(final FactHandle handle) {
+        for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+            if ( handle.equals( this.factHandles[i] ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle get(final int col) {
+        return this.factHandles[col];
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle get(final Declaration declaration) {
+        return this.get( declaration.getColumn().getFactIndex() );
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle[] getFactHandles() {
+        return this.factHandles;
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public void setActivation(final Activation activation) {
+        this.activation = activation;
+    }
+
+    /**
+     * to determine if "active" agendaItem needs to be valid from the queue on
+     * fact retraction
+     * 
+     * @return indicator if agendaItem was null'ed
+     */
+    protected boolean isActivationNull() {
+        return this.activation == null;
+    }
+
+    protected Activation getActivation() {
+        return this.activation;
+    }
+
+    public long getRecency() {
+        return 0;
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public boolean equals(final Object object) {
+        if ( this == object ) {
+            return true;
+        }
+
+        if ( object == null || !(object instanceof LeapsTuple) ) {
+            return false;
+        }
+
+        final FactHandle[] thatFactHandles = ((LeapsTuple) object).getFactHandles();
+        if ( thatFactHandles.length != this.factHandles.length ) {
+            return false;
+        }
+
+        for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+            if ( !this.factHandles[i].equals( thatFactHandles[i] ) ) {
+                return false;
+            }
+
+        }
+        return true;
+    }
+
+    /**
+     * indicates if exists conditions complete and there is no blocking facts
+     * 
+     * @return
+     */
+    protected boolean isReadyForActivation() {
+        return this.readyForActivation;
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public String toString() {
+        final StringBuffer buffer = new StringBuffer( "LeapsTuple [" + this.leapsRule.getRule().getName() + "] " );
+
+        for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+            buffer.append( ((i == 0) ? "" : ", ") + this.factHandles[i] );
+        }
+
+        if ( this.existsFactHandles != null ) {
+            buffer.append( "\nExists fact handles by position" );
+            for ( int i = 0, length = this.existsFactHandles.length; i < length; i++ ) {
+                buffer.append( "\nposition " + i ).append( this.existsFactHandles[i] );
+            }
+        }
+        if ( this.blockingNotFactHandles != null ) {
+            buffer.append( "\nblockingNot fact handles by position" );
+            for ( int i = 0, length = this.blockingNotFactHandles.length; i < length; i++ ) {
+                buffer.append( "\nposition " + i ).append( this.blockingNotFactHandles[i] );
+            }
+        }
+
+        return buffer.toString();
+    }
+
+    protected void setBlockingNotFactHandle(final LeapsFactHandle factHandle,
+                                            final int index) {
+        this.readyForActivation = false;
+        this.blockingNotFactHandles[index] = factHandle;
+    }
+
+    protected boolean isBlockingNotFactHandle(final int index) {
+        return this.blockingNotFactHandles[index] != null;
+    }
+
+    protected void removeBlockingNotFactHandle(final int index) {
+        this.blockingNotFactHandles[index] = null;
+        this.setReadyForActivation();
+    }
+
+    protected void setExistsFactHandle(final LeapsFactHandle factHandle,
+                                       final int index) {
+        this.existsFactHandles[index] = factHandle;
+        this.setReadyForActivation();
+    }
+
+    protected boolean isExistsFactHandle(final int index) {
+        return this.existsFactHandles[index] != null;
+    }
+
+    protected void removeExistsFactHandle(final int index) {
+        this.existsFactHandles[index] = null;
+        this.setReadyForActivation();
+    }
+
+    private void setReadyForActivation() {
+        this.readyForActivation = true;
+
+        if ( this.blockingNotFactHandles != null ) {
+            for ( int i = 0, length = this.blockingNotFactHandles.length; i < length; i++ ) {
+                if ( this.blockingNotFactHandles[i] != null ) {
+                    this.readyForActivation = false;
+                    return;
+                }
+            }
+        }
+
+        if ( this.existsFactHandles != null ) {
+            for ( int i = 0, length = this.existsFactHandles.length; i < length; i++ ) {
+                if ( this.existsFactHandles[i] == null ) {
+                    this.readyForActivation = false;
+                    return;
+                }
+            }
+        }
+    }
+
+    protected PropagationContext getContext() {
+        return this.context;
+    }
+
+    protected void setContext(final PropagationContext context) {
+        this.context = context;
+    }
+
+    public boolean isWasFired() {
+        return this.wasFired;
+    }
+
+    public void setWasFired(final boolean wasFired) {
+        this.wasFired = wasFired;
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,838 @@
+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.PropertyChangeListener;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.FactException;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.common.AbstractWorkingMemory;
+import org.drools.common.AgendaGroupImpl;
+import org.drools.common.AgendaItem;
+import org.drools.common.EventSupport;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.ScheduledAgendaItem;
+import org.drools.leaps.conflict.DefaultConflictResolver;
+import org.drools.leaps.util.TokenStack;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.Duration;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.IteratorChain;
+
+/**
+ * Followed RETEOO implementation for interfaces.
+ * 
+ * This class is a repository for leaps specific containers (fact factTables).
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.WorkingMemory
+ * @see java.beans.PropertyChangeListener
+ * @see java.io.Serializable
+ * 
+ */
+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 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();
+        this.agenda = new LeapsAgenda( this );
+    }
+
+    public void doAssertObject(final InternalFactHandle factHandle,
+                               final Object object,
+                               final PropagationContext propagationContext) throws FactException {
+
+        this.pushTokenOnStack( factHandle,
+                               new Token( this,
+                                          factHandle,
+                                          propagationContext ) );
+
+        // determine what classes it belongs to put it into the "table" on
+        // class name key
+        final 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 );
+            // iterate through unsatisfied exists
+            for ( final Iterator tuples = factTable.getTuplesIterator(); tuples.hasNext(); ) {
+                final LeapsTuple tuple = (LeapsTuple) tuples.next();
+
+                TokenEvaluator.evaluateExistsConditions( tuple,
+                                                         tuple.getLeapsRule(),
+                                                         this );
+                // check and see if we need activate
+                // activate only if tuple was not ready for it before
+                if ( tuple.isReadyForActivation() ) {
+                    // ready to activate
+                    tuplesToAssert.add( tuple );
+                }
+            }
+            for ( final Iterator it = tuplesToAssert.iterator(); it.hasNext(); ) {
+                // ready to activate
+                final LeapsTuple tuple = (LeapsTuple) it.next();
+                factTable.removeTuple( tuple );
+                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+                                                              PropagationContext.ASSERTION,
+                                                              tuple.getLeapsRule().getRule(),
+                                                              null ) );
+                this.assertTuple( tuple );
+            }
+        }
+        // inspect all tuples for not conditions and activate
+        // deactivate agenda items
+        final Activation[] activations = this.agenda.getActivations();
+        for ( int k = 0; k < activations.length; k++ ) {
+            boolean deActivate = false;
+            final LeapsTuple tuple = (LeapsTuple) activations[k].getTuple();
+            final ColumnConstraints[] not = tuple.getLeapsRule().getNotColumnConstraints();
+            for ( int i = 0, length = not.length; !deActivate && i < length; i++ ) {
+                final ColumnConstraints constraint = not[i];
+                final Object columnClassObject = constraint.getClassType();
+                if ( ((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 );
+                    deActivate = true;
+                }
+            }
+            // check and see if we need de-activate
+            if ( deActivate ) {
+                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+                                                              PropagationContext.ASSERTION,
+                                                              tuple.getLeapsRule().getRule(),
+                                                              null ) );
+                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
+     * 
+     * @see WorkingMemory
+     */
+    public void doRetract(final InternalFactHandle factHandle,
+                          final PropagationContext propagationContext) {
+
+        /*
+         * leaps specific actions
+         */
+        // remove fact from all relevant fact tables container
+        final Object objectClass = LeapsBuilder.getLeapsClassType( factHandle.getObject() );
+        for ( final Iterator it = this.getFactTablesList( objectClass ).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 ) {
+                // put query results to the working memory location
+                removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
+                                        tuple );
+            } else {
+                // time to pull from agenda
+                invalidateActivation( tuple );
+            }
+        }
+        ((LeapsFactHandle) factHandle).clearActivatedTuples();
+        // assert all tuples that are ready for activation or cancel ones
+        // that are no longer
+        Iterator it;
+        final IteratorChain chain = new IteratorChain();
+        it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
+        if ( it != null ) {
+            chain.addIterator( it );
+        }
+        it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
+        if ( it != null ) {
+            chain.addIterator( it );
+        }
+        for ( ; chain.hasNext(); ) {
+            final FactHandleTupleAssembly tupleAssembly = ((FactHandleTupleAssembly) chain.next());
+            final LeapsTuple tuple = tupleAssembly.getTuple();
+            if ( tupleAssembly.getType() == FactHandleTupleAssembly.NOT ) {
+                tuple.removeBlockingNotFactHandle( tupleAssembly.getIndex() );
+            } else {
+                tuple.removeExistsFactHandle( tupleAssembly.getIndex() );
+            }
+            // can assert only tuples that were not eligible for activation
+            // before retraction
+            if ( !TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+                                                                      tuple.getLeapsRule(),
+                                                                      this ) ) {
+                // deactivate tuple that was activated inside of
+                // processAfterAllPositive
+                // bad design, need to rethink it
+                invalidateActivation( tuple );
+            } else {
+                this.assertTuple( tuple );
+            }
+        }
+        ((LeapsFactHandle) factHandle).clearExistsTuples();
+        ((LeapsFactHandle) factHandle).clearNotTuples();
+        // remove it from stack
+        this.removeTokenFromStack( (LeapsFactHandle) factHandle );
+    }
+
+    /**
+     * 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();
+        // tuple can already loose activation if another fact or exists fact was retracted
+        // or not fact added
+        if ( activation != null ) {
+            if ( activation.isActivated() ) {
+                activation.remove();
+                this.getAgendaEventSupport().fireActivationCancelled( activation );
+            }
+
+            this.getTruthMaintenanceSystem().removeLogicalDependencies( activation,
+                                                                        tuple.getContext(),
+                                                                        tuple.getLeapsRule().getRule() );
+            //
+            tuple.setActivation( null );
+            // remove from rule / activaitons map
+            FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule() );
+            if ( activations != null ) {
+                activations.remove( activation );
+            }
+        }
+    }
+
+    /**
+     * ************* leaps section *********************
+     */
+    private long             idLastFireAllAt            = -1;
+
+    private boolean          rulesAddedSinceLastFireAll = false;
+
+    /**
+     * algorithm stack.
+     */
+    private final TokenStack mainStack                  = new TokenStack();
+
+    /**
+     * generates or just return List of internal factTables that correspond a
+     * class can be used to generate factTables
+     * 
+     * @return
+     */
+    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();
+            }
+        } else {
+            list.add( this.getFactTable( objectClass ) );
+        }
+        return list;
+    }
+
+    /**
+     * adds new leaps token on main stack
+     * 
+     * @param fact
+     *            handle
+     * @param token
+     */
+    protected final void pushTokenOnStack(final InternalFactHandle factHandle,
+                                          final Token token) {
+        this.mainStack.push( token );
+    }
+
+    /**
+     * removes leaps token on main stack
+     * 
+     * @param fact
+     *            handle
+     */
+    protected final void removeTokenFromStack(final LeapsFactHandle factHandle) {
+        this.mainStack.remove( factHandle.getId() );
+    }
+
+    /**
+     * gets leaps token from top of stack
+     * 
+     * @param fact
+     *            handle
+     */
+    protected final Token peekTokenOnTop() {
+        return (Token) this.mainStack.peek();
+    }
+
+    /**
+     * get leaps fact table of specific type (class)
+     * 
+     * @param type
+     *            of objects
+     * @return fact table of requested class type
+     */
+    protected FactTable getFactTable(final Object objectClass) {
+        FactTable 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 ) {
+                    final List rulesHandles = (List) this.leapsRulesToHandlesMap.get( leapsRule );
+                    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 );
+                        }
+                    }
+                }
+            }
+        }
+
+        return table;
+    }
+
+    /**
+     * Add Leaps wrapped rules into the working memory
+     * 
+     * @param rules
+     */
+    protected void addLeapsRules(final List rules) {
+        this.getLock().lock();
+        try {
+            this.rulesAddedSinceLastFireAll = true;
+
+            ArrayList ruleHandlesList;
+            LeapsRule rule;
+            LeapsRuleHandle ruleHandle;
+            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(),
+                                                          rule,
+                                                          i );
+                        // 
+                        if ( rule.getColumnConstraintsAtPosition( i ).getClass() != FromConstraint.class ) {
+                            this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) ).addRule( this,
+                                                                                                       ruleHandle );
+                            //
+                        } else {
+                            final 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 {
+                    this.noPositiveColumnsRules.add( new LeapsRuleHandle( ((LeapsFactHandleFactory) this.handleFactory).getNextId(),
+                                                                          rule,
+                                                                          0 ) );
+                }
+            }
+        } finally {
+            this.getLock().unlock();
+        }
+    }
+
+    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();
+                // some times rules do not have "normal" constraints and only
+                // not and exists
+                if ( leapsRule.getNumberOfColumns() > 0 ) {
+                    ruleHandlesList = (ArrayList) this.leapsRulesToHandlesMap.remove( leapsRule );
+                    for ( int i = 0; i < ruleHandlesList.size(); i++ ) {
+                        ruleHandle = (LeapsRuleHandle) ruleHandlesList.get( i );
+                        // 
+                        this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) ).removeRule( this,
+                                                                                                           ruleHandle );
+                    }
+                }
+                //
+            }
+            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 );
+                    this.tms.removeLogicalDependencies( activation,
+                                                        activation.getPropagationContext(),
+                                                        rule );
+                }
+            }
+
+            propagateQueuedActions();
+        } finally {
+            this.getLock().unlock();
+        }
+    }
+
+    /**
+     * main loop
+     * 
+     */
+    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 ) {
+            try {
+                this.firing = true;
+
+                boolean nothingToProcess = false;
+                while ( !nothingToProcess ) {
+                    // check for the initial fact
+                    for ( final Iterator rulesIt = this.noPositiveColumnsRules.iterator(); rulesIt.hasNext(); ) {
+                        final LeapsRule rule = ((LeapsRuleHandle) rulesIt.next()).getLeapsRule();
+                        final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter(),
+                                                                                           PropagationContext.ASSERTION,
+                                                                                           null, //rule.getRule( ),
+                                                                                           null );
+                        final LeapsTuple tuple = new LeapsTuple( new LeapsFactHandle[0],
+                                                                 rule,
+                                                                 context );
+                        if ( TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+                                                                                 rule,
+                                                                                 this ) ) {
+                            this.assertTuple( tuple );
+                        }
+
+                    }
+                    this.noPositiveColumnsRules.clear();
+                    // normal rules with required columns
+                    while ( !this.mainStack.empty() ) {
+                        final Token token = this.peekTokenOnTop();
+                        boolean done = false;
+                        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() );
+                                    done = true;
+                                }
+                            }
+                            if ( !done ) {
+                                try {
+                                    // 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 ) {
+                                        if ( token.getDominantFactHandle().getObject().getClass() != FromConstraintFactDriver.class ) {
+                                            token.setResume( true );
+                                        }
+                                        done = true;
+                                    }
+                                } 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 ) ) {
+                                ;
+                            }
+                        }
+                    }
+                    // pick activations generated by retraction or assert
+                    // can generate activations off exists and not pending
+                    // tuples
+                    while ( this.agenda.fireNextItem( agendaFilter ) ) {
+                        ;
+                    }
+                    if ( this.mainStack.empty() ) {
+                        nothingToProcess = true;
+                    }
+                }
+                // mark when method was called last time
+                this.rulesAddedSinceLastFireAll = false;
+                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 );
+                }
+                // clear table that is used to trigger From constraints
+                this.getFactTable( FromConstraintFactDriver.class ).clear();
+            } finally {
+                this.firing = false;
+            }
+        }
+    }
+
+    protected final boolean isRulesAddedSinceLastFireAll() {
+        return this.rulesAddedSinceLastFireAll;
+    }
+
+    protected final long getIdLastFireAllAt() {
+        return this.idLastFireAllAt;
+    }
+
+    public String toString() {
+        String ret = "";
+        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();
+            ret = ret + "\n" + "******************   " + key;
+            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();
+        }
+        return ret;
+    }
+
+    /**
+     * Assert a new <code>Tuple</code>.
+     * 
+     * @param tuple
+     *            The <code>Tuple</code> being asserted.
+     * @param workingMemory
+     *            The working memory seesion.
+     * @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();
+        // if the current Rule is no-loop and the origin rule is the same then
+        // return
+        if ( rule.getNoLoop() && rule.equals( context.getRuleOrigin() ) ) {
+            return;
+        }
+        //
+        final Duration dur = rule.getDuration();
+
+        Activation agendaItem;
+        if ( dur != null && dur.getDuration( tuple ) > 0 ) {
+            agendaItem = new ScheduledAgendaItem( context.getPropagationNumber(),
+                                                  tuple,
+                                                  this.agenda,
+                                                  context,
+                                                  rule );
+            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 ) ) {
+                    // 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 {
+                    // AgendaGroup is defined, so try and get the AgendaGroup
+                    // from the Agenda
+                    agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup() );
+                }
+
+                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() );
+                    this.agenda.addAgendaGroup( agendaGroup );
+                }
+
+                leapsRule.setAgendaGroup( agendaGroup );
+            }
+
+            // set the focus if rule autoFocus is true
+            if ( rule.getAutoFocus() ) {
+                this.agenda.setFocus( agendaGroup );
+            }
+
+            agendaItem = new AgendaItem( context.getPropagationNumber(),
+                                         tuple,
+                                         context,
+                                         rule );
+
+            agendaGroup.add( agendaItem );
+
+            tuple.setActivation( agendaItem );
+            agendaItem.setActivated( true );
+            this.getAgendaEventSupport().fireActivationCreated( agendaItem );
+        }
+
+        // retract support
+        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 );
+        }
+        activations.put( agendaItem,
+                         agendaItem );
+    }
+
+    List getActivations() {
+        final List ret = new ArrayList();
+        for ( final Iterator it = this.rulesActivationsMap.values().iterator(); it.hasNext(); ) {
+            ret.addAll( ((FastMap) it.next()).values() );
+        }
+
+        return ret;
+    }
+
+    protected long nextPropagationIdCounter() {
+        return ++this.propagationIdCounter;
+    }
+
+    public QueryResults getQueryResults(final String queryName) {
+        final IdentityMap map = (IdentityMap) this.queryResults.get( queryName );
+        if ( map == null ) {
+            return null;
+        }
+
+        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 {
+            return null;
+        }
+    }
+
+    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 );
+        }
+        map.put( tuple,
+                 tuple );
+    }
+
+    void removeFromQueryResults(final String query,
+                                final Tuple tuple) {
+        final IdentityMap map = (IdentityMap) this.queryResults.get( query );
+        if ( map != null ) {
+            map.remove( tuple );
+        }
+    }
+
+    /**
+     * to store facts to cursor over it
+     */
+    private final Map factTables = new FactTables();
+
+    class FactTables
+        implements
+        Map,
+        Serializable {
+        private final LinkedList tables = new LinkedList();
+
+        private final HashMap    map    = new HashMap();
+
+        public int size() {
+            return this.tables.size();
+        }
+
+        public void clear() {
+            this.tables.clear();
+            this.map.clear();
+        }
+
+        public boolean isEmpty() {
+            return this.tables.isEmpty();
+        }
+
+        public boolean containsKey(final Object key) {
+            return this.map.containsKey( key );
+        }
+
+        public boolean containsValue(final Object value) {
+            return this.map.containsValue( value );
+        }
+
+        public Collection values() {
+            return this.tables;
+        }
+
+        public void putAll(final Map t) {
+            this.tables.addAll( t.values() );
+            this.map.putAll( t );
+        }
+
+        public Set entrySet() {
+            return this.map.entrySet();
+        }
+
+        public Set keySet() {
+            return this.map.keySet();
+        }
+
+        public Object get(final Object key) {
+            return this.map.get( key );
+
+        }
+
+        public Object remove(final Object key) {
+            final Object ret = this.map.remove( key );
+            this.tables.remove( ret );
+            return ret;
+        }
+
+        public Object put(final Object key,
+                          final Object value) {
+            this.tables.add( value );
+            this.map.put( key,
+                          value );
+            return value;
+        }
+    }
+
+    private class FromConstraintFactDriver
+        implements
+        Serializable {
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+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.
+ */
+
+/**
+ * Exception to facilitate <code>seek</code> process in working memory
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+class NoMatchesFoundException extends Exception {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 1L;
+
+    public NoMatchesFoundException() {
+        super();
+    }
+
+    public NoMatchesFoundException(final String msg) {
+        super( msg );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,39 @@
+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.Comparator;
+
+import org.drools.leaps.util.Table;
+
+/**
+ * Implementation of a container to store data elements used throughout the
+ * leaps. Stores rule handles
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+class RuleTable extends Table {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -1855260276968132243L;
+
+    public RuleTable(final Comparator ruleConflictResolver) {
+        super( ruleConflictResolver );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,256 @@
+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.io.Serializable;
+import java.util.Iterator;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * this object wears multiple hats - Tuple and being main element that wraps
+ * fact handle on main leaps stack
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class Token
+    implements
+    Tuple,
+    Serializable {
+
+    private static final long        serialVersionUID   = 1L;
+
+    private LeapsWorkingMemory       workingMemory;
+
+    private final InternalFactHandle dominantFactHandle;
+
+    private LeapsRuleHandle          currentRuleHandle  = null;
+
+    private LeapsFactHandle[]        currentFactHandles = new LeapsFactHandle[0];
+
+    boolean                          resume             = false;
+
+    private Iterator                 rules              = null;
+
+    private final PropagationContext propagationContext;
+
+    /**
+     * 
+     */
+    public Token(final LeapsWorkingMemory workingMemory,
+                 final InternalFactHandle factHandle,
+                 final PropagationContext propagationContext) {
+        this.workingMemory = workingMemory;
+        this.dominantFactHandle = factHandle;
+        this.propagationContext = propagationContext;
+    }
+
+    private Iterator rulesIterator() {
+        if ( this.rules == null ) {
+            if ( this.dominantFactHandle != null ) {
+                this.rules = this.workingMemory.getFactTable( LeapsBuilder.getLeapsClassType( this.dominantFactHandle.getObject() ) ).getRulesIterator();
+            }
+        }
+        return this.rules;
+    }
+
+    public LeapsRuleHandle nextRuleHandle() {
+        this.currentRuleHandle = (LeapsRuleHandle) this.rules.next();
+        this.currentFactHandles = new LeapsFactHandle[this.currentRuleHandle.getLeapsRule().getNumberOfColumns()];
+        return this.currentRuleHandle;
+    }
+
+    /**
+     * 
+     * @param memory
+     * @return indicator if there are more rules
+     */
+
+    public boolean hasNextRuleHandle() {
+        boolean ret = false;
+        if ( this.rulesIterator() != null ) {
+            // starting with calling rulesIterator() to make sure that we picks
+            // rules because fact can be asserted before rules added
+            final long levelId = (this.workingMemory.isRulesAddedSinceLastFireAll()) ? this.workingMemory.getIdLastFireAllAt() : -1;
+
+            if ( this.dominantFactHandle == null || this.dominantFactHandle.getRecency() >= levelId ) {
+                ret = this.rules.hasNext();
+            } else {
+                // then we need to skip rules that have id lower than
+                // workingMemory.idLastFireAllAt
+                boolean done = false;
+                while ( !done ) {
+                    if ( this.rules.hasNext() ) {
+                        if ( ((LeapsRuleHandle) ((TableIterator) this.rules).peekNext()).getRecency() > levelId ) {
+                            ret = true;
+                            done = true;
+                        } else {
+                            this.rules.next();
+                        }
+                    } else {
+                        ret = false;
+                        done = true;
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    public int hashCode() {
+        if ( this.dominantFactHandle != null ) {
+            return this.dominantFactHandle.hashCode();
+        } else {
+            return 0;
+        }
+    }
+
+    public void set(final int idx,
+                    final LeapsFactHandle factHandle) {
+        this.currentFactHandles[idx] = factHandle;
+    }
+
+    public InternalFactHandle getDominantFactHandle() {
+        return this.dominantFactHandle;
+    }
+
+    public LeapsRuleHandle getCurrentRuleHandle() {
+        return this.currentRuleHandle;
+    }
+
+    public boolean isResume() {
+        return this.resume;
+    }
+
+    public void setResume(final boolean resume) {
+        this.resume = resume;
+    }
+
+    /**
+     * We always have only one Tuple per fact handle hence match on handle id
+     * 
+     * @see Object
+     */
+    public boolean equals(final Object that) {
+        return this.dominantFactHandle.getId() == ((Token) that).dominantFactHandle.getId();
+    }
+
+    /**
+     * Retrieve the value at position
+     * 
+     * @param position
+     * @return The currently bound <code>Object</code> value.
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle get(final int idx) {
+        return this.currentFactHandles[idx];
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle get(final Declaration declaration) {
+        return this.get( declaration.getColumn().getFactIndex() );
+    }
+
+    /**
+     * @see org.drools.spi.Tuple
+     */
+    public InternalFactHandle[] getFactHandles() {
+        return this.currentFactHandles;
+    }
+
+    public long getRecency() {
+        return 0;
+    }
+
+    /**
+     * Returns a reference to the <code>WorkingMemory</code> associated with
+     * this object.
+     * 
+     * @return WorkingMemory
+     */
+    public WorkingMemory getWorkingMemory() {
+        return this.workingMemory;
+    }
+
+    /**
+     * @see java.lang.Object
+     */
+    public String toString() {
+        String ret = "TOKEN [" + this.dominantFactHandle + "]\n" + "\tRULE : " + this.currentRuleHandle + "\n";
+        if ( this.currentFactHandles != null ) {
+            for ( int i = 0, length = this.currentFactHandles.length; i < length; i++ ) {
+                ret = ret + ((i == this.currentRuleHandle.getDominantPosition()) ? "***" : "") + "\t" + i + " -> " + this.currentFactHandles[i].getObject() + "\n";
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * creates lightweight tuple suitable for agendaItem
+     * 
+     * @return LeapsTuple
+     */
+    LeapsTuple getTuple() {
+        return new LeapsTuple( this.currentFactHandles,
+                               this.currentRuleHandle.getLeapsRule(),
+                               this.propagationContext );
+    }
+
+    /**
+     * Determine if this tuple depends upon a specified object.
+     * 
+     * @param handle
+     *            The object handle to test.
+     * 
+     * @return <code>true</code> if this tuple depends upon the specified
+     *         object, otherwise <code>false</code>.
+     */
+    public boolean dependsOn(final FactHandle handle) {
+        for ( int i = 0, length = this.currentFactHandles.length; i < length; i++ ) {
+            if ( this.currentFactHandles[i].equals( handle ) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Do nothing because this tuple never gets to agendaItem stage. Another one -
+     * LeapsTuple - is created to take part in agendaItem processing
+     * 
+     * @see getTuple()
+     * @see org.drools.spi.Tuple
+     */
+    public void setActivation(final Activation activation) {
+        // do nothing
+    }
+
+    public PropagationContext getPropagationContext() {
+        return this.propagationContext;
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,358 @@
+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.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
+ * seek. all methods are static
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+final class TokenEvaluator {
+    /**
+     * this method does nested loops iterations on all relavant fact tables and
+     * evaluates rules conditions
+     * 
+     * @param token
+     * @throws NoMatchesFoundException
+     * @throws Exception
+     * @throws InvalidRuleException
+     */
+    final static protected void evaluate(final Token token) throws NoMatchesFoundException,
+                                                           InvalidRuleException {
+        final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) token.getWorkingMemory();
+        final LeapsRule leapsRule = token.getCurrentRuleHandle().getLeapsRule();
+        // sometimes there is no normal conditions, only not and exists
+        final int numberOfColumns = leapsRule.getNumberOfColumns();
+        // if (numberOfColumns > 0) {
+        final int dominantFactPosition = token.getCurrentRuleHandle().getDominantPosition();
+        final InternalFactHandle dominantFactHandle = token.getDominantFactHandle();
+        if ( leapsRule.getColumnConstraintsAtPosition( dominantFactPosition ).isAllowedAlpha( dominantFactHandle,
+                                                                                              token,
+                                                                                              workingMemory ) ) {
+            final Object dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
+            final TableIterator[] iterators = new TableIterator[numberOfColumns];
+            // getting iterators first
+            for ( int i = 0; i < numberOfColumns; i++ ) {
+                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 {
+                        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
+            // check if we resume and any starting facts disappeared than we
+            // do not do skip on resume
+            boolean doReset = false;
+            boolean skip = token.isResume();
+            TableIterator currentIterator;
+            for ( int i = 0; i < numberOfColumns; i++ ) {
+                currentIterator = iterators[i];
+                if ( currentIterator != null ) {
+                    // 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;
+                            }
+                        } else {
+                            currentIterator.reset();
+                        }
+                    }
+                }
+            }
+
+            // iterating is done in nested loop
+            // column position in the nested loop
+            int jj = 0;
+            boolean done = false;
+            final int stopIteratingCount = numberOfColumns - 1;
+            while ( !done ) {
+                currentIterator = iterators[jj];
+                // if it's not From and does not have next
+                if ( currentIterator != null && !currentIterator.hasNext() ) {
+                    if ( jj == 0 ) {
+                        done = true;
+                    } else {
+                        // nothing for this column, go back and check next
+                        // on the one level up in nested loop
+                        currentIterator.reset();
+                        jj = jj - 1;
+                        if ( skip ) {
+                            skip = false;
+                        }
+                    }
+                } else {
+                    boolean localMatch = false;
+                    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 {
+                        final 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 ) {
+                        token.set( jj,
+                                   currentFactHandle );
+                        // start iteratating next iterator or for the last
+                        // one check negative conditions and fire consequence
+                        if ( jj == stopIteratingCount ) {
+                            if ( !skip ) {
+                                final LeapsTuple tuple = token.getTuple();
+                                if ( processAfterAllPositiveConstraintOk( tuple,
+                                                                          leapsRule,
+                                                                          workingMemory ) ) {
+                                    workingMemory.assertTuple( tuple );
+                                    return;
+                                }
+                            } else {
+                                skip = false;
+                            }
+                        } else {
+                            jj = jj + 1;
+                        }
+                    }
+                }
+            }
+        }
+        // nothing was found. inform caller about it
+        throw new NoMatchesFoundException();
+    }
+
+    /**
+     * Makes final check on eval, exists and not conditions after all column
+     * values isAllowed by column constraints
+     * 
+     * @param token
+     * @param leapsRule
+     * @param workingMemory
+     * @return
+     * @throws Exception
+     */
+    final static boolean processAfterAllPositiveConstraintOk(final LeapsTuple tuple,
+                                                             final LeapsRule leapsRule,
+                                                             final LeapsWorkingMemory workingMemory) {
+        if ( leapsRule.containsEvalConditions() && !TokenEvaluator.evaluateEvalConditions( tuple,
+                                                                                           leapsRule,
+                                                                                           workingMemory ) ) {
+            return false;
+        }
+        if ( leapsRule.containsExistsColumns() ) {
+            TokenEvaluator.evaluateExistsConditions( tuple,
+                                                     leapsRule,
+                                                     workingMemory );
+        }
+        if ( tuple.isReadyForActivation() && leapsRule.containsNotColumns() ) {
+            TokenEvaluator.evaluateNotConditions( tuple,
+                                                  leapsRule,
+                                                  workingMemory );
+        }
+        // 
+        return tuple.isReadyForActivation();
+    }
+
+    /**
+     * checks is EvalConditions isAllowed()
+     * 
+     * @param leapsRule
+     * @param tuple
+     * @param workingMemory
+     * @return
+     * @throws Exception
+     */
+    private final static Object evaluateFrom(final FromConstraint from,
+                                             final Tuple tuple,
+                                             final LeapsRule leapsRule,
+                                             final LeapsWorkingMemory workingMemory) {
+        for ( final Iterator it = from.getProvider().getResults( tuple,
+                                                           workingMemory,
+                                                           null ); it.hasNext(); ) {
+            final 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++ ) {
+            if ( !evals[i].isAllowed( tuple,
+                                      workingMemory ) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Check if any of the negative conditions are satisfied success when none
+     * found
+     * 
+     * @param memory
+     * @param token
+     * @return success
+     * @throws Exception
+     */
+    final static void evaluateNotConditions(final LeapsTuple tuple,
+                                            final LeapsRule rule,
+                                            final LeapsWorkingMemory workingMemory) {
+        // stops if exists
+        boolean done = false;
+        final ColumnConstraints[] not = rule.getNotColumnConstraints();
+        for ( int i = 0, length = not.length; i < length && !done; i++ ) {
+            final ColumnConstraints constraint = not[i];
+            // scan table starting at start fact handle
+            final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType() ).reverseOrderIterator( tuple,
+                                                                                                                              constraint );
+            while ( !done && tableIterator.hasNext() ) {
+                final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next();
+                // check constraint conditions
+                if ( constraint.isAllowed( factHandle,
+                                           tuple,
+                                           workingMemory ) ) {
+                    tuple.setBlockingNotFactHandle( factHandle,
+                                                    i );
+                    factHandle.addNotTuple( tuple,
+                                            i );
+                    done = true;
+                }
+            }
+        }
+    }
+
+    /**
+     * Check if any of the exists conditions are satisfied
+     * 
+     * @param tuple
+     * @param memory
+     * @throws Exception
+     */
+    public final static void evaluateExistsConditions(final LeapsTuple tuple,
+                                                      final LeapsRule rule,
+                                                      final LeapsWorkingMemory workingMemory) {
+        // stop if exists
+        boolean notFound = false;
+        boolean done = false;
+        final ColumnConstraints[] exists = rule.getExistsColumnConstraints();
+        for ( int i = 0, length = exists.length; !notFound && i < length; i++ ) {
+            final ColumnConstraints constraint = exists[i];
+            if ( !tuple.isExistsFactHandle( i ) ) {
+                // scan table starting at start fact handle
+                final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType() ).reverseOrderIterator( tuple,
+                                                                                                                                  constraint );
+                done = false;
+                while ( !done && tableIterator.hasNext() ) {
+                    final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next();
+                    // check constraint conditions
+                    if ( constraint.isAllowed( factHandle,
+                                               tuple,
+                                               workingMemory ) ) {
+                        tuple.setExistsFactHandle( factHandle,
+                                                   i );
+                        factHandle.addExistsTuple( tuple,
+                                                   i );
+                        done = true;
+                    }
+                }
+                if ( !done ) {
+                    notFound = true;
+                    workingMemory.getFactTable( constraint.getClassType() ).addTuple( tuple );
+                }
+            }
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,47 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.Comparator;
+
+import org.drools.leaps.ConflictResolver;
+
+/**
+ * A blueprint for conflict resolers
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+
+abstract class AbstractConflictResolver
+    implements
+    ConflictResolver {
+    // need for comparator
+    static int compare(final int i1,
+                       final int i2) {
+        return i1 - i2;
+    }
+
+    static int compare(final long l1,
+                       final long l2) {
+        return (int) (l1 - l2);
+    }
+
+    public abstract Comparator getFactConflictResolver();
+
+    public abstract Comparator getRuleConflictResolver();
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,91 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Strategy for resolving conflicts amongst multiple rules.
+ * 
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+
+class CompositeConflictResolver extends AbstractConflictResolver {
+    final Comparator[] factResolvers;
+
+    final Comparator[] ruleResolvers;
+
+    public CompositeConflictResolver(final Comparator[] factResolvers,
+                                     final Comparator[] ruleResolvers) {
+        this.factResolvers = factResolvers;
+        this.ruleResolvers = ruleResolvers;
+    }
+
+    public final Comparator getFactConflictResolver() {
+        return new FactConflictResolver();
+    }
+
+    class FactConflictResolver
+        implements
+        Comparator,
+        Serializable {
+        public int compare(final Object o1,
+                           final Object o2) {
+            int ret = 0;
+            if ( o1 != o2 ) {
+                for ( int i = 0, length = CompositeConflictResolver.this.factResolvers.length; ret == 0 && i < length; ++i ) {
+                    ret = CompositeConflictResolver.this.factResolvers[i].compare( o1,
+                                                                                   o2 );
+                }
+            }
+            return ret;
+        }
+    }
+
+    public final Comparator getRuleConflictResolver() {
+        return new RuleConflictResolver();
+    }
+
+    class RuleConflictResolver
+        implements
+        Comparator,
+        Serializable {
+        public int compare(final Object o1,
+                           final Object o2) {
+            int ret = 0;
+            if ( o1 != o2 ) {
+                for ( int i = 0, length = CompositeConflictResolver.this.ruleResolvers.length; ret == 0 && i < length; ++i ) {
+                    ret = CompositeConflictResolver.this.ruleResolvers[i].compare( o1,
+                                                                                   o2 );
+                }
+            }
+            return ret;
+        }
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,63 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.Comparator;
+
+import org.drools.leaps.ConflictResolver;
+
+/**
+ * Default strategy for resolving conflicts amongst multiple rules.
+ * 
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+public class DefaultConflictResolver extends CompositeConflictResolver {
+
+    private static final Comparator[]            FACT_CONFLICT_RESOLVERS = new Comparator[]{LoadOrderConflictResolver.getInstance()};
+
+    private static final Comparator[]            RULE_CONFLICT_RESOLVERS = new Comparator[]{RuleSalienceConflictResolver.getInstance(), RuleComplexityConflictResolver.getInstance(), LoadOrderConflictResolver.getInstance()};
+
+    /** Singleton instance. */
+    private static final DefaultConflictResolver INSTANCE                = new DefaultConflictResolver();
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static ConflictResolver getInstance() {
+        return DefaultConflictResolver.INSTANCE;
+    }
+
+    /**
+     * Setup a default ConflictResolver configuration
+     */
+    public DefaultConflictResolver() {
+        super( DefaultConflictResolver.FACT_CONFLICT_RESOLVERS,
+               DefaultConflictResolver.RULE_CONFLICT_RESOLVERS );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,66 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.common.DefaultFactHandle;
+
+/**
+ * <code>LoadOrderConflictResolver</code> that uses the load order of rules to
+ * resolve conflict.
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+public class LoadOrderConflictResolver
+    implements
+    Comparator,
+    Serializable {
+
+    /** Singleton instance. */
+    private static final LoadOrderConflictResolver INSTANCE = new LoadOrderConflictResolver();
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static Comparator getInstance() {
+        return LoadOrderConflictResolver.INSTANCE;
+    }
+
+    /**
+     * Construct.
+     */
+    private LoadOrderConflictResolver() {
+        // intentionally left blank
+    }
+
+    /**
+     * @see LeapsRuleConflictResolver
+     */
+    public int compare(final Object o1,
+                       final Object o2) {
+        return (-1) * AbstractConflictResolver.compare( ((DefaultFactHandle) o1).getRecency(),
+                                                        ((DefaultFactHandle) o2).getRecency() );
+    };
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,65 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the rule complexity.
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleComplexityConflictResolver
+    implements
+    Comparator,
+    Serializable {
+
+    /** Singleton instance. */
+    private static final RuleComplexityConflictResolver INSTANCE = new RuleComplexityConflictResolver();
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static Comparator getInstance() {
+        return RuleComplexityConflictResolver.INSTANCE;
+    }
+
+    /**
+     * Construct.
+     */
+    private RuleComplexityConflictResolver() {
+        // intentionally left blank
+    }
+
+    /**
+     * @see LeapsRuleConflictResolver
+     */
+    public int compare(final Object o1,
+                       final Object o2) {
+        return (-1) * AbstractConflictResolver.compare( (((LeapsRuleHandle) o1).getRuleComplexity()),
+                                                        (((LeapsRuleHandle) o2).getRuleComplexity()) );
+    };
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,69 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the load order of rules to
+ * resolve conflict.
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleLoadOrderConflictResolver
+    implements
+    Comparator {
+
+    /** Singleton instance. */
+    private static final RuleLoadOrderConflictResolver INSTANCE = new RuleLoadOrderConflictResolver();
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static Comparator getInstance() {
+        return RuleLoadOrderConflictResolver.INSTANCE;
+    }
+
+    /**
+     * Construct.
+     */
+    private RuleLoadOrderConflictResolver() {
+        // intentionally left blank
+    }
+
+    /**
+     * @see LeapsRuleLoadOrderResolver
+     */
+    public int compare(final Object o1,
+                       final Object o2) {
+        int ret = LoadOrderConflictResolver.getInstance().compare( o1,
+                                                                   o2 );
+        if ( ret == 0 ) {
+            ret = (-1) * AbstractConflictResolver.compare( ((LeapsRuleHandle) o1).getDominantPosition(),
+                                                           ((LeapsRuleHandle) o2).getDominantPosition() );
+        }
+        return ret;
+    };
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,65 @@
+package org.drools.leaps.conflict;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the salience of rules to
+ * resolve conflict.
+ * 
+ * @author Alexander Bagerman
+ * 
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleSalienceConflictResolver
+    implements
+    Comparator,
+    Serializable {
+    /** Singleton instance. */
+    private static final RuleSalienceConflictResolver INSTANCE = new RuleSalienceConflictResolver();
+
+    /**
+     * Retrieve the singleton instance.
+     * 
+     * @return The singleton instance.
+     */
+    public static Comparator getInstance() {
+        return RuleSalienceConflictResolver.INSTANCE;
+    }
+
+    /**
+     * Construct.
+     */
+    private RuleSalienceConflictResolver() {
+        // intentionally left blank
+    }
+
+    /**
+     * @see LeapsRuleConflictResolver
+     */
+    public int compare(final Object o1,
+                       final Object o2) {
+        return (-1) * AbstractConflictResolver.compare( ((LeapsRuleHandle) o1).getSalience(),
+                                                        ((LeapsRuleHandle) o2).getSalience() );
+    };
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,111 @@
+package org.drools.leaps.util;
+
+/*
+ * 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 org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.leaps.ColumnConstraints;
+
+/**
+ * this class is for multi pass iterations to sort out facts that do not satisfy
+ * alpha nodes
+ * 
+ * previous to the left
+ * next to the right
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class ConstrainedIteratorFromPositionToTableStart extends IteratorFromPositionToTableStart {
+    private boolean         finishInitialPass = false;
+
+    final WorkingMemory     workingMemory;
+
+    final ColumnConstraints constraints;
+
+    private TableRecord     currentTableRecord;
+
+    protected ConstrainedIteratorFromPositionToTableStart(final WorkingMemory workingMemory,
+                                                          final ColumnConstraints constraints,
+                                                          final TableRecord startRecord,
+                                                          final TableRecord currentRecord) {
+        super( null );
+        this.workingMemory = workingMemory;
+        this.constraints = constraints;
+        this.currentTableRecord = startRecord;
+        boolean done = false;
+        boolean reachCurrentRecord = false;
+        while ( !done && this.currentTableRecord != null && !this.finishInitialPass ) {
+            if ( !reachCurrentRecord && this.currentTableRecord == currentRecord ) {
+                reachCurrentRecord = true;
+            } else {
+                if ( this.constraints.isAllowedAlpha( (InternalFactHandle) this.currentTableRecord.object,
+                                                      null,
+                                                      this.workingMemory ) ) {
+                    this.add( this.currentTableRecord.object );
+                }
+                if ( reachCurrentRecord && !this.isEmpty() ) {
+                    done = true;
+                }
+                if ( this.currentTableRecord.right == null ) {
+                    this.finishInitialPass = true;
+                }
+                this.currentTableRecord = this.currentTableRecord.right;
+            }
+        }
+    }
+
+    private void add(final Object object) {
+        final TableRecord record = new TableRecord( object );
+        if ( this.firstRecord == null ) {
+            this.firstRecord = record;
+            this.currentRecord = record;
+        } else {
+            this.currentRecord.right = record;
+            record.left = this.currentRecord;
+            this.currentRecord = record;
+        }
+
+        this.nextRecord = this.currentRecord;
+    }
+
+    public boolean hasNext() {
+        if ( !this.finishInitialPass ) {
+            if ( this.nextRecord == null ) {
+                boolean found = false;
+                while ( !found && this.currentTableRecord != null ) {
+                    if ( this.constraints.isAllowedAlpha( (InternalFactHandle) this.currentTableRecord.object,
+                                                          null,
+                                                          this.workingMemory ) ) {
+                        this.add( this.currentTableRecord.object );
+                        found = true;
+                    }
+                    if ( this.currentTableRecord == null ) {
+                        this.finishInitialPass = true;
+                    }
+                    this.currentTableRecord = this.currentTableRecord.right;
+                }
+
+                return found;
+            } else {
+                return true;
+            }
+        } else {
+            return super.hasNext();
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,63 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.NoSuchElementException;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigation
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class IteratorFromPositionToTableEnd extends IteratorFromPositionToTableStart {
+    /**
+     * @see IteratorFromPositionToTableStart
+     */
+    protected IteratorFromPositionToTableEnd(final TableRecord record) {
+        super( record );
+    }
+
+    /**
+     * @see IteratorFromPositionToTableStart
+     */
+    protected IteratorFromPositionToTableEnd(final TableRecord startRecord,
+                                             final TableRecord currentRecord) {
+        super( startRecord,
+               currentRecord );
+    }
+
+    /**
+     * the difference here is that we are going to the different direction that
+     * base class next() method
+     * 
+     * @see IteratorFromPositionToTableStart
+     * 
+     */
+
+    public Object next() {
+        this.currentRecord = this.nextRecord;
+        if ( this.currentRecord != null ) {
+            this.nextRecord = this.currentRecord.left;
+        } else {
+            throw new NoSuchElementException( "No more elements to return" );
+        }
+        return this.currentRecord.object;
+    }
+
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,91 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.NoSuchElementException;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigation
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class IteratorFromPositionToTableStart
+    implements
+    TableIterator {
+    /**
+     * interator that was not initialized as "empty" iterator (one or another
+     * record was submitted to constractor) will set it to false
+     */
+    TableRecord firstRecord;
+
+    TableRecord currentRecord;
+
+    TableRecord nextRecord;
+
+    /**
+     * constracts an leaps iterator to iterate over a single record. Used for
+     * Dominant fact dimention iteration
+     * 
+     * @param record
+     *            to iterate over
+     */
+
+    protected IteratorFromPositionToTableStart(final TableRecord record) {
+        this.firstRecord = record;
+        this.currentRecord = null;
+        this.nextRecord = this.firstRecord;
+    }
+
+    public IteratorFromPositionToTableStart(final TableRecord startRecord,
+                                            final TableRecord currentRecord) {
+        this.firstRecord = startRecord;
+        this.nextRecord = currentRecord;
+        this.currentRecord = null;
+    }
+
+    public boolean isEmpty() {
+        return this.firstRecord == null;
+    }
+
+    public void reset() {
+        this.currentRecord = null;
+        this.nextRecord = this.firstRecord;
+    }
+
+    public boolean hasNext() {
+        return this.nextRecord != null;
+    }
+
+    public Object next() {
+        this.currentRecord = this.nextRecord;
+        if ( this.currentRecord != null ) {
+            this.nextRecord = this.currentRecord.right;
+        } else {
+            throw new NoSuchElementException( "No more elements to return" );
+        }
+        return this.currentRecord.object;
+    }
+
+    public Object peekNext() {
+        return this.nextRecord.object;
+    }
+
+    public void remove() {
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,46 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * this class wraps object comparator to sort records holding given objects in
+ * a list
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+
+class RecordComparator
+    implements
+    Comparator,
+    Serializable {
+    private Comparator objectComparator;
+
+    RecordComparator(final Comparator objectComparator) {
+        this.objectComparator = objectComparator;
+    }
+
+    public int compare(final Object record1,
+                       final Object record2) {
+        return this.objectComparator.compare( ((TableRecord) record1).object,
+                                              ((TableRecord) record2).object );
+    }
+
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,344 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.io.Serializable;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.TreeSet;
+
+import org.drools.WorkingMemory;
+import org.drools.leaps.ColumnConstraints;
+
+/**
+ * double linked list structure to store objects in the ordered list 
+ * and iterate over the list for leaps 
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class Table
+    implements
+    Serializable {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 2614082619270512055L;
+
+    private final TreeSet     set;
+
+    protected TableRecord     headRecord;
+
+    protected TableRecord     tailRecord;
+
+    private boolean           empty            = true;
+
+    private int               count            = 0;
+
+    public Table(final Comparator comparator) {
+        this.set = new TreeSet( new RecordComparator( comparator ) );
+    }
+
+    public void clear() {
+        this.headRecord = null;
+        this.empty = true;
+        this.count = 0;
+        this.set.clear();
+    }
+
+    /**
+     * @param object
+     *            to add
+     */
+    public void add(final Object object) {
+        final TableRecord newRecord = new TableRecord( object );
+        if ( this.empty ) {
+            this.headRecord = newRecord;
+            this.empty = false;
+        } else {
+            try {
+                // check on first key should work faster than check on empty
+                // but logically we check on empty
+                // if map empty it will throw exception
+                final TableRecord bufRec = (TableRecord) this.set.headSet( newRecord ).last();
+                if ( bufRec.right != null ) {
+                    bufRec.right.left = newRecord;
+                }
+                newRecord.right = bufRec.right;
+                bufRec.right = newRecord;
+                newRecord.left = bufRec;
+
+            } catch ( final NoSuchElementException nsee ) {
+                // means sub map is empty
+                this.headRecord.left = newRecord;
+                newRecord.right = this.headRecord;
+                this.headRecord = newRecord;
+            }
+        }
+        // check if the new record was added at the end of the list
+        // and assign new value to the tail record
+        if ( newRecord.right == null ) {
+            this.tailRecord = newRecord;
+        }
+        //
+        this.count++;
+        //
+        this.set.add( newRecord );
+    }
+
+    /**
+     * Removes object from the table
+     * 
+     * @param object
+     *            to remove from the table
+     */
+    public void remove(final Object object) {
+        if ( !this.empty ) {
+            try {
+                final TableRecord record = (TableRecord) this.set.tailSet( new TableRecord( object ) ).first();
+                if ( record != null && record.object == object ) {
+                    if ( record == this.headRecord ) {
+                        if ( record.right != null ) {
+                            this.headRecord = record.right;
+                            this.headRecord.left = null;
+                        } else {
+                            // single element in table being valid
+                            // table is empty now
+                            this.headRecord = null;
+                            this.tailRecord = null;
+                            this.empty = true;
+                        }
+                    } else if ( record == this.tailRecord ) {
+                        // single element in the table case is being solved
+                        // above in check for headRecord match
+                        this.tailRecord = record.left;
+                        this.tailRecord.right = null;
+                    } else {
+                        // left
+                        record.left.right = record.right;
+                        record.right.left = record.left;
+                    }
+                    record.left = null;
+                    record.right = null;
+                } else {
+                    throw new NoSuchElementException();
+                }
+                this.count--;
+                //
+                this.set.remove( record );
+            } catch ( final NoSuchElementException nsee ) {
+                throw nsee;
+            }
+        }
+    }
+
+    /**
+     * @param object
+     * @return indicator of presence of given object in the table
+     */
+    public boolean contains(final Object object) {
+        boolean ret = false;
+        if ( !this.empty ) {
+            ret = this.set.contains( new TableRecord( object ) );
+        }
+        return ret;
+    }
+
+    /**
+     * @return TableIterator for this Table
+     * @see org.drools.leaps.util.TableIterator
+     * @see org.drools.leaps.util.IteratorFromPositionToTableStart
+     */
+    public TableIterator iterator() {
+        TableIterator ret;
+        if ( this.empty ) {
+            ret = new IteratorFromPositionToTableStart( null,
+                                                        null );
+        } else {
+            ret = new IteratorFromPositionToTableStart( this.headRecord,
+                                                        this.headRecord );
+        }
+        return ret;
+    }
+
+    public TableIterator reverseOrderIterator() {
+        TableIterator ret;
+        if ( this.empty ) {
+            ret = new IteratorFromPositionToTableEnd( null,
+                                                      null );
+        } else {
+            ret = new IteratorFromPositionToTableEnd( this.tailRecord,
+                                                      this.tailRecord );
+        }
+        return ret;
+    }
+
+    /**
+     * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+     * iterator at objectAtPosition for resumed iterations 
+     * 
+     * @param objectAtStart -
+     *            upper boundary of the iteration
+     * @param objectAtPosition -
+     *            starting point of the iteration
+     * @return leaps table iterator
+     * @throws TableOutOfBoundException
+     */
+    public TableIterator constrainedIteratorFromPositionToTableStart(final WorkingMemory workingMemory,
+                                                                     final ColumnConstraints constraints,
+                                                                     final Object objectAtStart,
+                                                                     final Object objectAtPosition) {
+        return getIteratorFromPositionToTableStart( true,
+                                                    workingMemory,
+                                                    constraints,
+                                                    objectAtStart,
+                                                    objectAtPosition );
+    }
+
+    /**
+     * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+     * iterator at objectAtPosition for resumed iterations 
+     * 
+     * @param objectAtStart -
+     *            upper boundary of the iteration
+     * @param objectAtPosition -
+     *            starting point of the iteration
+     * @return leaps table iterator
+     * @throws TableOutOfBoundException
+     */
+    public TableIterator iteratorFromPositionToTableStart(final Object objectAtStart,
+                                                          final Object objectAtPosition) {
+        return getIteratorFromPositionToTableStart( false,
+                                                    null,
+                                                    null,
+                                                    objectAtStart,
+                                                    objectAtPosition );
+    }
+
+    /**
+     * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+     * iterator at objectAtPosition for resumed iterations 
+     * 
+     * @param objectAtStart -
+     *            upper boundary of the iteration
+     * @param objectAtPosition -
+     *            starting point of the iteration
+     * @return leaps table iterator
+     * @throws TableOutOfBoundException
+     */
+    public TableIterator iteratorFromPositionToTableEnd(final Object objectAtStart) {
+        TableRecord record = null;
+        try {
+            record = (TableRecord) this.set.headSet( new TableRecord( objectAtStart ) ).last();
+        } catch ( final NoSuchElementException nsee ) {
+        }
+
+        return new IteratorFromPositionToTableEnd( record,
+                                                   record );
+    }
+
+    /**
+     * retrieve Markers structure for a given objectAtStart.  
+     * 
+     * @param objectAtStart -
+     *            upper boundary of the iteration
+     * @return Markers structure
+     */
+    private TableIterator getIteratorFromPositionToTableStart(final boolean isConstraint,
+                                                              final WorkingMemory workingMemory,
+                                                              final ColumnConstraints constraints,
+                                                              final Object objectAtStart,
+                                                              final Object objectAtPosition) {
+        TableRecord startRecord = null;
+        TableRecord currentRecord = null;
+
+        final TableRecord recordAtStart = new TableRecord( objectAtStart );
+        if ( !this.empty ) {
+            try {
+                // check on first key should work faster than check
+                // to see if set has no elements
+                // if set is empty it will throw exception
+                startRecord = (TableRecord) this.set.tailSet( recordAtStart ).first();
+                if ( objectAtStart == objectAtPosition ) {
+                    currentRecord = startRecord;
+                } else {
+                    // rewind to position
+                    try {
+                        // check on first key should work faster than check
+                        // to see if set has no elements
+                        // if set is empty it will throw exception
+                        currentRecord = (TableRecord) this.set.tailSet( new TableRecord( objectAtPosition ) ).first();
+                    } catch ( final NoSuchElementException nsee ) {
+                        currentRecord = startRecord;
+                    }
+                }
+            } catch ( final NoSuchElementException nsee ) {
+            }
+        }
+
+        if ( isConstraint ) {
+            return new ConstrainedIteratorFromPositionToTableStart( workingMemory,
+                                                                    constraints,
+                                                                    startRecord,
+                                                                    currentRecord );
+        } else {
+            return new IteratorFromPositionToTableStart( startRecord,
+                                                         currentRecord );
+        }
+    }
+
+    /**
+     * indicates if table has any elements
+     * 
+     * @return empty indicator
+     */
+    public boolean isEmpty() {
+        return this.empty;
+    }
+
+    public String toString() {
+        String ret = "";
+
+        for ( final Iterator it = this.iterator(); it.hasNext(); ) {
+            ret = ret + it.next() + "\n";
+        }
+        return ret;
+    }
+
+    public int size() {
+        return this.count;
+    }
+
+    public Object top() {
+        return this.headRecord.object;
+    }
+
+    public Object bottom() {
+        return this.tailRecord.object;
+    }
+
+    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-leaps/src/main/java/org/drools/leaps/util/TableIterator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,47 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.Iterator;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigating
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public interface TableIterator
+    extends
+    Iterator {
+    /**
+     * single object iterator
+     * 
+     * @return table iterator
+     */
+    public boolean isEmpty();
+
+    public void reset();
+
+    public boolean hasNext();
+
+    public Object next();
+
+    public Object peekNext();
+
+    public void remove();
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,60 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.io.Serializable;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+public class TableRecord
+    implements
+    Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 2894253746310217052L;
+
+    // left neigbor
+    TableRecord               left;
+
+    // right neigbor
+    TableRecord               right;
+
+    // content of the record
+    Object                    object;
+
+    TableRecord(final Object o) {
+        this.left = null;
+        this.right = null;
+        this.object = o;
+    }
+
+    public int hashCode() {
+        return this.object.hashCode();
+    }
+
+    public boolean equals(final Object that) {
+        if ( this.object != null ) {
+            return this.object.equals( ((TableRecord) that).object );
+        } else {
+            return that == null;
+        }
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,131 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.io.Serializable;
+import java.util.EmptyStackException;
+import java.util.Iterator;
+
+import org.drools.leaps.Token;
+import org.drools.util.PrimitiveLongMap;
+
+/**
+ * This class follows java.util.Stack interface but accounts for remove( object )
+ * functionallity needed by leaps
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+
+public class TokenStack
+    implements
+    Serializable {
+
+    protected TableRecord          tailRecord = null;
+
+    private final PrimitiveLongMap map        = new PrimitiveLongMap();
+
+    public TokenStack() {
+
+    }
+
+    public boolean empty() {
+        return this.tailRecord == null;
+    }
+
+    public Object peek() {
+        if ( this.tailRecord != null ) {
+            return this.tailRecord.object;
+        } else {
+            throw new EmptyStackException();
+        }
+    }
+
+    public Object pop() {
+        if ( this.tailRecord != null ) {
+            final Object ret = this.tailRecord.object;
+            final TableRecord buf = this.tailRecord;
+            this.tailRecord = buf.left;
+            if ( buf.left != null ) {
+                this.tailRecord.right = null;
+            }
+            buf.left = null;
+
+            this.map.remove( ((Token) ret).getDominantFactHandle().getId() );
+            return ret;
+        } else {
+            throw new EmptyStackException();
+        }
+    }
+
+    /**
+     * Removes object from the table
+     * 
+     * @param object
+     *            to remove from the table
+     */
+    public void remove(final long factId) {
+        if ( this.tailRecord != null ) {
+            final TableRecord record = (TableRecord) this.map.remove( factId );
+
+            if ( record != null ) {
+                if ( record == this.tailRecord ) {
+                    this.tailRecord = record.left;
+                }
+                if ( record.left != null ) {
+                    record.left.right = record.right;
+                }
+                if ( record.right != null ) {
+                    record.right.left = record.left;
+                }
+                record.left = null;
+                record.right = null;
+            }
+        }
+    }
+
+    public Object push(final Object item) {
+        final TableRecord record = new TableRecord( item );
+        if ( this.tailRecord != null ) {
+            this.tailRecord.right = record;
+            record.left = this.tailRecord;
+        }
+        this.tailRecord = record;
+
+        this.map.put( ((Token) item).getDominantFactHandle().getId(),
+                      record );
+        return item;
+    }
+
+    public Iterator iterator() {
+        return new Iterator() {
+            Iterator it = TokenStack.this.map.values().iterator();
+
+            public boolean hasNext() {
+                return this.it.hasNext();
+            }
+
+            public void remove() {
+
+            }
+
+            public Object next() {
+                return this.it.next();
+            }
+        };
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,164 @@
+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 org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.LiteralConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.MockField;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class ColumnConstraintsTest extends DroolsTestCase {
+
+    Evaluator integerEqualEvaluator;
+
+    Evaluator integerNotEqualEvaluator;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+        this.integerNotEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.NOT_EQUAL );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+     * WorkingMemoryImpl)'
+     */
+    public void testEvaluateAlphasSuccess() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        final ArrayList alphas = new ArrayList();
+        ColumnConstraints columnConstraints;
+        AlphaNodeFieldConstraint constraint;
+        final ClassObjectType contextType = new ClassObjectType( Context.class );
+        final Column testColumn = new Column( 0,
+                                              contextType,
+                                              "state" );
+
+        constraint = getLiteralConstraint( testColumn,
+                                           "state",
+                                           new Integer( Context.START_UP ),
+                                           this.integerEqualEvaluator );
+        alphas.add( constraint );
+        testColumn.addConstraint( constraint );
+        constraint = getLiteralConstraint( testColumn,
+                                           "state",
+                                           new Integer( -999999 ),
+                                           this.integerNotEqualEvaluator );
+        alphas.add( constraint );
+        testColumn.addConstraint( constraint );
+
+        columnConstraints = new ColumnConstraints( testColumn,
+                                                   alphas,
+                                                   null );
+
+        final LeapsTuple tuple = new LeapsTuple( new LeapsFactHandle[0],
+                                                 null,
+                                                 null );
+        assertTrue( columnConstraints.isAllowed( new LeapsFactHandle( 23,
+                                                                      new Context( Context.START_UP ) ),
+                                                 tuple,
+                                                 ruleBase.newWorkingMemory() ) );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+     * WorkingMemoryImpl)'
+     */
+    public void testEvaluateAlphasFalure() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        final ArrayList alphas = new ArrayList();
+        ColumnConstraints columnConstraints;
+        AlphaNodeFieldConstraint constraint;
+        final ClassObjectType contextType = new ClassObjectType( Context.class );
+        final Column testColumn = new Column( 0,
+                                              contextType,
+                                              "state" );
+
+        constraint = getLiteralConstraint( testColumn,
+                                           "state",
+                                           new Integer( Context.START_UP ),
+                                           this.integerEqualEvaluator );
+        alphas.add( constraint );
+        testColumn.addConstraint( constraint );
+        constraint = getLiteralConstraint( testColumn,
+                                           "state",
+                                           new Integer( -999999 ),
+                                           this.integerEqualEvaluator );
+        alphas.add( constraint );
+        testColumn.addConstraint( constraint );
+
+        columnConstraints = new ColumnConstraints( testColumn,
+                                                   alphas,
+                                                   null );
+
+        assertFalse( columnConstraints.isAllowed( new LeapsFactHandle( 23,
+                                                                       new Context( Context.START_UP ) ),
+                                                  null,
+                                                  ruleBase.newWorkingMemory() ) );
+
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+                                                          final String fieldName,
+                                                          final Object fieldValue,
+                                                          final Evaluator evaluator) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+        final FieldValue field = new MockField( fieldValue );
+
+        final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+                                                                  fieldName );
+
+        return new LiteralConstraint( extractor,
+                                      evaluator,
+                                      field );
+    }
+
+    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;
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,94 @@
+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.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.ObjectType;
+
+public class CrossProductTest extends TestCase {
+    public void test1() throws Exception {
+        final ObjectType list1ObjectType = new ClassObjectType( List.class );
+        final ObjectType list2ObjectType = new ClassObjectType( List.class );
+
+        final Rule rule = new Rule( "rule-1" );
+
+        final Column list1Column = new Column( 0,
+                                               list1ObjectType,
+                                               "list1" );
+        final Column list2Column = new Column( 1,
+                                               list2ObjectType,
+                                               "list2" );
+
+        rule.addPattern( list1Column );
+        rule.addPattern( list2Column );
+
+        final Declaration list1Declaration = rule.getDeclaration( "list1" );
+        final Declaration list2Declaration = rule.getDeclaration( "list2" );
+
+        final List values = new ArrayList();
+
+        rule.setConsequence( new Consequence() {
+
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -958666414598812063L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) throws Exception {
+                final List list1 = (List) knowledgeHelper.get( list1Declaration );
+                final List list2 = (List) knowledgeHelper.get( list2Declaration );
+                values.add( new List[]{list1, list2} );
+            }
+
+        } );
+
+        final Package pkg = new Package( "org.drools" );
+        pkg.addRule( rule );
+
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        ruleBase.addPackage( pkg );
+
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+        workingMemory.assertObject( new ArrayList() );
+        workingMemory.assertObject( new ArrayList() );
+        workingMemory.assertObject( new LinkedList() );
+        workingMemory.assertObject( new LinkedList() );
+
+        workingMemory.fireAllRules();
+
+        // A full cross product is 16, this is just 12
+        assertEquals( 12,
+                      values.size() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,61 @@
+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 junit.framework.TestCase;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class FactHandleImplTest extends TestCase {
+
+    private LeapsRuleBase ruleBase;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+    }
+
+    /*
+     * Test method for 'leaps.LeapsFactHandle.getId()'
+     */
+    public void testGetId() {
+        final LeapsWorkingMemory memory = (LeapsWorkingMemory) this.ruleBase.newWorkingMemory();
+
+        try {
+            final FactHandle fh1 = memory.assertObject( "object1" );
+            assertEquals( ((LeapsFactHandle) fh1).getId(),
+                          ((LeapsFactHandle) memory.getFactHandleFactory().newFactHandle( "dummy" )).getId() - 1 );
+        } catch ( final FactException fe ) {
+        }
+    }
+
+    /*
+     * Test method for 'leaps.LeapsFactHandle.equals(Object)'
+     */
+    public void testEqualsObject() {
+        // they equal on id, am not sure how to simulate it yet
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,98 @@
+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 junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class HandleFactoryTest extends TestCase {
+
+    LeapsFactHandleFactory factory;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.factory = new LeapsFactHandleFactory();
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.Handlethis.factory.newFactHandle()'
+     */
+    public void testNewFactHandle() {
+        final Object object = new Object();
+        assertTrue( ((DefaultFactHandle) this.factory.newFactHandle( object )).getObject() == object );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.Handlethis.factory.getNextId()'
+     */
+    public void testGetNextId() {
+        this.factory.getNextId();
+        this.factory.getNextId();
+        this.factory.getNextId();
+        this.factory.getNextId();
+
+        final long nextId = this.factory.getNextId() + 1;
+        assertEquals( nextId,
+                      this.factory.getNextId() );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools.leaps.Handlethis.factory.newFactHandle(Object)'
+     */
+    public void testNewFactHandleObject() {
+        this.factory.getNextId();
+        this.factory.getNextId();
+
+        final String testObject = new String( "test object" );
+        final long nextId = this.factory.getNextId() + 1;
+        final DefaultFactHandle handle = (DefaultFactHandle) this.factory.newFactHandle( testObject );
+        assertEquals( nextId,
+                      handle.getId() );
+        assertEquals( testObject,
+                      handle.getObject() );
+
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.Handlethis.factory.newFactHandle(long)'
+     */
+    public void testNewFactHandleLong() {
+        this.factory.getNextId();
+        this.factory.getNextId();
+
+        final long nextId = this.factory.getNextId() + 1;
+        assertEquals( nextId,
+                      ((DefaultFactHandle) this.factory.newFactHandle( 984393L,
+                                                                       new Object() )).getId() );
+
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.Handlethis.factory.newInstance()'
+     */
+    public void testNewInstance() {
+        assertFalse( this.factory == this.factory.newInstance() );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+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 junit.framework.TestCase;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class HandleTest extends TestCase {
+
+    /*
+     * Test method for 'leaps.LeapsFactHandle.getId()'
+     */
+    public void testGetId() {
+        final LeapsFactHandle handle = new LeapsFactHandle( 123456789,
+                                                            new String( "test124" ) );
+        assertEquals( handle.getId(),
+                      123456789 );
+        assertEquals( handle.getObject(),
+                      "test124" );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,418 @@
+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.Iterator;
+
+import org.drools.DroolsTestCase;
+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.examples.manners.Path;
+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.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+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 {
+
+        final 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;
+        final FactTable ft = wm.getFactTable( Path.class );
+        final ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints().next();
+        final LeapsFactHandle[] fh = new LeapsFactHandle[1];
+        fh[0] = new LeapsFactHandle( 99,
+                                     this.p1Alex );
+        tuple = new LeapsTuple( fh,
+                                null,
+                                null );
+
+        it = ft.reverseOrderIterator( tuple,
+                                      notConstraint );
+        assertSame( "Expected matching",
+                    ((LeapsFactHandle) it.next()).getObject(),
+                    this.p1Alex );
+        assertSame( "Expected matching",
+                    ((LeapsFactHandle) it.next()).getObject(),
+                    this.p5Alex );
+        assertFalse( "Did not expect any more data",
+                     it.hasNext() );
+
+        fh[0] = new LeapsFactHandle( 99,
+                                     this.p3Mike );
+        tuple = new LeapsTuple( fh,
+                                null,
+                                null );
+
+        it = ft.reverseOrderIterator( tuple,
+                                      notConstraint );
+        assertSame( "Expected matching",
+                    ((LeapsFactHandle) it.next()).getObject(),
+                    this.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 {
+
+        final 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;
+        final FactTable ft = wm.getFactTable( Path.class );
+        final ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints().next();
+        final LeapsFactHandle[] fh = new LeapsFactHandle[1];
+        fh[0] = new LeapsFactHandle( 99,
+                                     this.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,
+                                     this.p3Mike );
+        tuple = new LeapsTuple( fh,
+                                null,
+                                null );
+
+        it = ft.reverseOrderIterator( tuple,
+                                      notConstraint );
+        assertSame( "Expected matching",
+                    ((LeapsFactHandle) it.next()).getObject(),
+                    this.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 AlphaNodeFieldConstraint 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 AlphaNodeFieldConstraint 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 );
+    }
+
+}

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+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 junit.framework.TestCase;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsFactHandleTest extends TestCase {
+
+    /*
+     * Test method for 'leaps.LeapsFactHandle.getId()'
+     */
+    public void testGetId() {
+        final LeapsFactHandle handle = new LeapsFactHandle( 123456789,
+                                                            new String( "test124" ) );
+        assertEquals( handle.getId(),
+                      123456789 );
+        assertEquals( handle.getObject(),
+                      "test124" );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,400 @@
+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 org.drools.DroolsTestCase;
+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.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+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 LeapsRuleBaseTest extends DroolsTestCase {
+    LeapsRuleBase   ruleBase;
+    LeapsRuleBase   ruleBaseAddRule;
+
+    WorkingMemory   wm1;
+
+    WorkingMemory   wm2;
+
+    WorkingMemory   wm3;
+
+    WorkingMemory   wm4;
+
+    // leaps add rule objects
+    final String    handle1Rule1    = "11";
+
+    final String    handle1Rule2    = "12";
+
+    final String    handle2Rule1    = "21";
+
+    final String    handle2Rule2    = "22";
+
+    final ArrayList handlesForRules = new ArrayList();
+
+    WorkingMemory   workingMemory;
+
+    Rule            rule1;
+
+    Rule            rule2;
+
+    final Context   context1        = new Context( 1 );
+
+    final Context   context2        = new Context( 1 );
+
+    public void setUp() throws Exception {
+        this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        this.wm1 = this.ruleBase.newWorkingMemory();
+        this.wm2 = this.ruleBase.newWorkingMemory();
+        this.wm3 = this.ruleBase.newWorkingMemory();
+        this.wm4 = this.ruleBase.newWorkingMemory();
+        // add rules section
+        this.ruleBaseAddRule = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        this.workingMemory = this.ruleBaseAddRule.newWorkingMemory();
+        // rules
+        final ClassObjectType contextType = new ClassObjectType( Context.class );
+        final Evaluator integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+        // rule 1
+        // fires on context.state == integer(1)
+        this.rule1 = new Rule( "rule1" );
+        final Column contextColumnRule1 = new Column( 0,
+                                                      contextType,
+                                                      "context1" );
+        contextColumnRule1.addConstraint( getLiteralConstraint( contextColumnRule1,
+                                                                "state",
+                                                                new Integer( 1 ),
+                                                                integerEqualEvaluator ) );
+        this.rule1.addPattern( contextColumnRule1 );
+        final Declaration contextRule1Declaration = this.rule1.getDeclaration( "context1" );
+        this.rule1.setConsequence( new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -143645020218500159L;
+
+            public void evaluate(final KnowledgeHelper drools,
+                                 final WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    final Rule rule = drools.getRule();
+                    final Tuple tuple = drools.getTuple();
+
+                    final Context dummy = (Context) drools.get( contextRule1Declaration );
+                    if ( dummy == LeapsRuleBaseTest.this.context1 ) {
+                        LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle1Rule1 );
+                    } else if ( dummy == LeapsRuleBaseTest.this.context2 ) {
+                        LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle2Rule1 );
+                    }
+
+                } catch ( final Exception e ) {
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        } );
+        this.rule2 = new Rule( "rule2" );
+        final Column contextColumnRule2 = new Column( 0,
+                                                      contextType,
+                                                      "context2" );
+        contextColumnRule2.addConstraint( getLiteralConstraint( contextColumnRule2,
+                                                                "state",
+                                                                new Integer( 1 ),
+                                                                integerEqualEvaluator ) );
+        this.rule2.addPattern( contextColumnRule2 );
+        final Declaration contextRule2Declaration = this.rule2.getDeclaration( "context2" );
+        this.rule2.setConsequence( new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 6203944847152159644L;
+
+            public void evaluate(final KnowledgeHelper drools,
+                                 final WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    final Rule rule = drools.getRule();
+                    final Tuple tuple = drools.getTuple();
+
+                    final Context dummy = (Context) drools.get( contextRule2Declaration );
+                    if ( dummy == LeapsRuleBaseTest.this.context1 ) {
+                        LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle1Rule2 );
+                    } else if ( dummy == LeapsRuleBaseTest.this.context2 ) {
+                        LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle2Rule2 );
+                    }
+
+                } catch ( final Exception e ) {
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        } );
+    }
+
+    public void testKeepReference() throws Exception {
+        /* Make sure the RuleBase is referencing all 4 Working Memories */
+        assertLength( 4,
+                      this.ruleBase.getWorkingMemories() );
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm1 ) );
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm2 ) );
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm4 ) );
+    }
+
+    public void testWeakReference() throws Exception {
+        /* nulling these two so the keys should get garbage collected */
+        this.wm2 = null;
+        this.wm4 = null;
+
+        /* Run GC */
+        System.gc();
+        Thread.sleep( 200 ); // Shouldn't need to sleep, but put it in anyway
+
+        /* Check we now only have two keys */
+        assertLength( 2,
+                      this.ruleBase.getWorkingMemories() );
+
+        /* Make sure the correct keys were valid */
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm1 ) );
+        assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm2 ) );
+        assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+        assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm4 ) );
+
+    }
+
+    public void testDispose() throws Exception {
+        /*
+         * Now lets test the dispose method on the WorkingMemory itself. dispose
+         * doesn't need GC
+         */
+        this.wm3.dispose();
+
+        /* Check only wm3 was valid */
+        assertLength( 3,
+                      this.ruleBase.getWorkingMemories() );
+        assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+    }
+
+    public void testNoKeepReference() throws Exception {
+        final WorkingMemory wm5 = this.ruleBase.newWorkingMemory( false );
+        final WorkingMemory wm6 = this.ruleBase.newWorkingMemory( false );
+        assertLength( 4,
+                      this.ruleBase.getWorkingMemories() );
+        assertFalse( this.ruleBase.getWorkingMemories().contains( wm5 ) );
+        assertFalse( this.ruleBase.getWorkingMemories().contains( wm6 ) );
+    }
+
+    public void testAddRuleBeforeFacts() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        this.workingMemory.assertObject( this.context1 );
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleMixedWithFacts() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        this.workingMemory.assertObject( this.context1 );
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleAfterFacts() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+        this.workingMemory.assertObject( this.context1 );
+        this.workingMemory.assertObject( this.context2 );
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleBeforeFactsFiring() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleMixedWithFactsFiring1() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleMixedWithFactsFiring2() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context2 );
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    public void testAddRuleAfterFactsFiring() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+        this.workingMemory.assertObject( this.context1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        // firing
+        this.workingMemory.fireAllRules();
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 4,
+                      this.handlesForRules.size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+                                                          final String fieldName,
+                                                          final Object fieldValue,
+                                                          final Evaluator evaluator) {
+        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 );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,128 @@
+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 junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.common.AgendaItem;
+
+/**
+ * @author Alexander Bagerman
+ */
+public class LeapsTupleTest extends TestCase {
+
+    LeapsTuple      tuple;
+
+    LeapsFactHandle h1;
+
+    LeapsFactHandle h2;
+
+    LeapsFactHandle h3;
+
+    LeapsFactHandle h4;
+
+    LeapsFactHandle hOutsider;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.h1 = new LeapsFactHandle( 1,
+                                       "one" );
+        this.h2 = new LeapsFactHandle( 2,
+                                       "two" );
+        this.h3 = new LeapsFactHandle( 3,
+                                       "three" );
+        this.h4 = new LeapsFactHandle( 4,
+                                       "four" );
+        final LeapsFactHandle arr[] = {this.h1, this.h2, this.h3, this.h4};
+        this.tuple = new LeapsTuple( arr,
+                                     null,
+                                     null );
+
+        this.hOutsider = new LeapsFactHandle( 9876,
+                                              "outsider" );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.dependsOn(FactHandle)'
+     */
+    public void testDependsOn() {
+        assertTrue( this.tuple.dependsOn( this.h3 ) );
+        assertFalse( this.tuple.dependsOn( this.hOutsider ) );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.get(int)'
+     */
+    public void testGetInt() {
+        assertEquals( this.tuple.get( 3 ),
+                      this.h4 );
+
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.get(Declaration)'
+     */
+    public void testGetDeclaration() {
+
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.getFactHandles()'
+     */
+    public void testGetFactHandles() {
+        final FactHandle[] arr = this.tuple.getFactHandles();
+        for ( int i = 0; i < arr.length; i++ ) {
+            assertEquals( arr[0],
+                          this.h1 );
+            assertEquals( arr[1],
+                          this.h2 );
+            assertEquals( arr[2],
+                          this.h3 );
+            assertEquals( arr[3],
+                          this.h4 );
+
+        }
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.isActivationNull()'
+     */
+    public void testIsActivationNull() {
+        final AgendaItem item = new AgendaItem( 0L,
+                                                this.tuple,
+                                                null,
+                                                null );
+        assertTrue( this.tuple.isActivationNull() );
+        this.tuple.setActivation( item );
+        assertFalse( this.tuple.isActivationNull() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.LeapsTuple.equals(Object)'
+     */
+    public void testEqualsObject() {
+        final LeapsFactHandle arr[] = {this.h1, this.h2, this.h3, this.h4};
+        final LeapsTuple tupleToCompare = new LeapsTuple( arr,
+                                                          null,
+                                                          null );
+        assertEquals( this.tuple,
+                      tupleToCompare );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,68 @@
+package org.drools.leaps;
+
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.EqualityKey;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.TruthMaintenanceSystem;
+
+public class LeapsWorkingMemoryTest extends TestCase {
+    /*
+     * @see JBRULES-356
+     */
+    public void testBasicWorkingMemoryActions() {
+        final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) RuleBaseFactory.newRuleBase( RuleBase.LEAPS ).newWorkingMemory();
+        final TruthMaintenanceSystem tms = workingMemory.getTruthMaintenanceSystem();
+        final String string = "test";
+        FactHandle fd = workingMemory.assertObject( string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        EqualityKey key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+
+        workingMemory.modifyObject( fd,
+                                    string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+
+        workingMemory.retractObject( fd );
+
+        assertEquals( 0,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertNull( key );
+
+        fd = workingMemory.assertObject( string );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+
+        assertEquals( 1,
+                      tms.getAssertMap().size() );
+        key = tms.get( string );
+        assertSame( fd,
+                    key.getFactHandle() );
+        assertNull( key.getOtherFactHandle() );
+    }
+
+    public void testId() {
+        final LeapsRuleBase ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newWorkingMemory();
+        assertEquals( 0,
+                      workingMemory.getId() );
+        workingMemory = (InternalWorkingMemory) ruleBase.newWorkingMemory();
+        assertEquals( 1,
+                      workingMemory.getId() );
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,367 @@
+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 org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author Alexander Bagerman
+ */
+public class LogicalAssertionTest extends DroolsTestCase {
+
+    Consequence        consequence;
+
+    LeapsRuleBase      ruleBase;
+
+    LeapsWorkingMemory workingMemory;
+
+    public void setUp() throws Exception {
+        super.setUp();
+        this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        this.workingMemory = (LeapsWorkingMemory) this.ruleBase.newWorkingMemory();
+        this.consequence = new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -3536436180370109113L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                // do nothing
+            }
+        };
+    }
+
+    public void testEqualsMap() throws Exception {
+        // create a RuleBase with a single ObjectTypeNode we attach a
+        // MockObjectSink so we can detect assertions and retractions
+
+        final Rule rule1 = new Rule( "test-rule1" );
+
+        rule1.setConsequence( this.consequence );
+
+        final LeapsRule leapsRule1 = new LeapsRule( rule1,
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList() );
+
+        final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
+        PropagationContext context1;
+        LeapsTuple tuple1;
+
+        final String logicalString1 = new String( "logical" );
+        final FactHandle handle1 = ((LeapsFactHandleFactory) this.ruleBase.getFactHandleFactory()).newFactHandle( logicalString1 );
+        context1 = new PropagationContextImpl( 1,
+                                               PropagationContext.ASSERTION,
+                                               rule1,
+                                               null );
+        factHandles[0] = (LeapsFactHandle) handle1;
+        tuple1 = new LeapsTuple( factHandles,
+                                 leapsRule1,
+                                 context1 );
+        this.workingMemory.assertTuple( tuple1 );
+        FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+                                                                     false,
+                                                                     true,
+                                                                     null,
+                                                                     this.workingMemory.getAgenda().getActivations()[0] );
+
+        final String logicalString2 = new String( "logical" );
+        FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+                                                                     false,
+                                                                     true,
+                                                                     rule1,
+                                                                     this.workingMemory.getAgenda().getActivations()[0] );
+        factHandles[0] = (LeapsFactHandle) logicalHandle2;
+        tuple1 = new LeapsTuple( factHandles,
+                                 leapsRule1,
+                                 context1 );
+        this.workingMemory.assertTuple( tuple1 );
+
+        assertSame( logicalHandle1,
+                    logicalHandle2 );
+
+        // little sanity check using normal assert
+        logicalHandle1 = this.workingMemory.assertObject( logicalString1 );
+        logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+        assertNotSame( logicalHandle1,
+                       logicalHandle2 );
+
+    }
+
+    /**
+     * This tests that Stated asserts always take precedent
+     * 
+     * @throws Exception
+     */
+    public void testStatedOverride() throws Exception {
+        final Rule rule1 = new Rule( "test-rule1" );
+
+        rule1.setConsequence( this.consequence );
+
+        final LeapsRule leapsRule1 = new LeapsRule( rule1,
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList() );
+
+        final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
+        PropagationContext context1;
+        LeapsTuple tuple1;
+
+        String logicalString1 = new String( "logical" );
+        final FactHandle handle1 = ((LeapsFactHandleFactory) this.ruleBase.getFactHandleFactory()).newFactHandle( logicalString1 );
+        context1 = new PropagationContextImpl( 1,
+                                               PropagationContext.ASSERTION,
+                                               rule1,
+                                               null );
+        factHandles[0] = (LeapsFactHandle) handle1;
+        tuple1 = new LeapsTuple( factHandles,
+                                 leapsRule1,
+                                 context1 );
+        this.workingMemory.assertTuple( tuple1 );
+        FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+                                                                     false,
+                                                                     true,
+                                                                     null,
+                                                                     this.workingMemory.getAgenda().getActivations()[0] );
+
+        String logicalString2 = new String( "logical" );
+        FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+
+        // Should keep the same handle when overriding
+        assertSame( logicalHandle1,
+                    logicalHandle2 );
+
+        // so while new STATED assertion is equal
+        assertEquals( logicalString1,
+                      this.workingMemory.getObject( logicalHandle2 ) );
+        // they are not - not identity same - leaps can not store two objects if
+        // handles are the same
+        assertNotSame( logicalString1,
+                       this.workingMemory.getObject( logicalHandle2 ) );
+
+        assertSame( logicalString2,
+                    this.workingMemory.getObject( logicalHandle2 ) );
+
+        // Test that a logical assertion cannot override a STATED assertion
+        factHandles[0] = (LeapsFactHandle) logicalHandle2;
+        tuple1 = new LeapsTuple( factHandles,
+                                 leapsRule1,
+                                 context1 );
+        this.workingMemory.assertTuple( tuple1 );
+
+        logicalString2 = new String( "logical" );
+        logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+
+        // This logical assertion will be ignored as there is already
+        // an equals STATED assertion.
+        logicalString1 = new String( "logical" );
+        logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+                                                          false,
+                                                          true,
+                                                          null,
+                                                          this.workingMemory.getAgenda().getActivations()[0] );
+        // Already an equals object but not identity same, so will do nothing
+        // and return null
+        assertNull( logicalHandle1 );
+
+        //        // Alreyad identify same so return previously assigned handle
+        //        logicalHandle1 = this.workingMemory.assertObject( logicalString2,
+        //                                                          false,
+        //                                                          true,
+        //                                                          null,
+        //                                                          this.workingMemory.getAgenda().getActivations()[0] );
+        //        // return the matched handle
+        //        assertSame( logicalHandle2,
+        //                    logicalHandle1 );
+        //
+        //        this.workingMemory.retractObject( handle1 );
+        //
+        //        // Should keep the same handle when overriding
+        //        assertSame( logicalHandle1,
+        //                    logicalHandle2 );
+        //
+        //        // so while new STATED assertion is equal
+        //        assertEquals( logicalString1,
+        //                      this.workingMemory.getObject( logicalHandle2 ) );
+        //
+        //        // they are not identity same
+        //        assertNotSame( logicalString1,
+        //                       this.workingMemory.getObject( logicalHandle2 ) );
+        //
+    }
+
+    public void testRetract() throws Exception {
+        final Rule rule1 = new Rule( "test-rule1" );
+        // create the first agendaItem which will justify the fact "logical"
+        rule1.setConsequence( this.consequence );
+
+        final LeapsRule leapsRule1 = new LeapsRule( rule1,
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList() );
+
+        final LeapsFactHandle tuple1FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
+        final LeapsFactHandle tuple2FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple2 object" );
+        final LeapsFactHandle[] factHandlesTuple1 = new LeapsFactHandle[1];
+        final LeapsFactHandle[] factHandlesTuple2 = new LeapsFactHandle[1];
+        factHandlesTuple1[0] = tuple1FactHandle;
+        factHandlesTuple2[0] = tuple2FactHandle;
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule1,
+                                                                       null );
+        LeapsTuple tuple1 = new LeapsTuple( factHandlesTuple1,
+                                            leapsRule1,
+                                            context );
+        final LeapsTuple tuple2 = new LeapsTuple( factHandlesTuple2,
+                                                  leapsRule1,
+                                                  context );
+        this.workingMemory.assertTuple( tuple1 );
+        final Activation activation1 = this.workingMemory.getAgenda().getActivations()[0];
+
+        // Assert the logical "logical" fact
+        final String logicalString1 = new String( "logical" );
+        final FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+                                                                           false,
+                                                                           true,
+                                                                           rule1,
+                                                                           activation1 );
+        assertEquals( 3,
+                      this.workingMemory.getObjects().size() );
+
+        // create the second agendaItem to justify the "logical" fact
+        final Rule rule2 = new Rule( "test-rule2" );
+        rule2.setConsequence( this.consequence );
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule2,
+                                                                        null );
+        tuple1 = new LeapsTuple( factHandlesTuple2,
+                                 leapsRule1,
+                                 context2 );
+        this.workingMemory.assertTuple( tuple1 );
+        final Activation activation2 = this.workingMemory.getAgenda().getActivations()[1];
+        //
+        final String logicalString2 = new String( "logical" );
+        final FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+                                                                           false,
+                                                                           true,
+                                                                           rule1,
+                                                                           activation2 );
+        // "logical" should only appear once
+        assertEquals( 3,
+                      this.workingMemory.getObjects().size() );
+
+        // retract the logical object
+        this.workingMemory.retractObject( logicalHandle2 );
+
+        // The logical object should never appear
+        assertEquals( 2,
+                      this.workingMemory.getObjects().size() );
+
+    }
+
+    public void testMultipleLogicalRelationships() throws FactException {
+        final Rule rule1 = new Rule( "test-rule1" );
+        // create the first agendaItem which will justify the fact "logical"
+        rule1.setConsequence( this.consequence );
+
+        final LeapsRule leapsRule1 = new LeapsRule( rule1,
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList(),
+                                                    new ArrayList() );
+
+        final LeapsFactHandle tuple1Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
+        final LeapsFactHandle tuple2Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple2 object" );
+        final LeapsFactHandle[] tuple1Handles = new LeapsFactHandle[1];
+        final LeapsFactHandle[] tuple2Handles = new LeapsFactHandle[1];
+        tuple1Handles[0] = tuple1Fact;
+        tuple2Handles[0] = tuple2Fact;
+
+        final PropagationContext context1 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule1,
+                                                                        null );
+        final LeapsTuple tuple1 = new LeapsTuple( tuple1Handles,
+                                                  leapsRule1,
+                                                  context1 );
+        this.workingMemory.assertTuple( tuple1 );
+        final Activation activation1 = this.workingMemory.getAgenda().getActivations()[0];
+
+        // Assert the logical "logical" fact
+        final String logicalString1 = new String( "logical" );
+        final FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+                                                                           false,
+                                                                           true,
+                                                                           rule1,
+                                                                           activation1 );
+
+        // create the second agendaItem to justify the "logical" fact
+        final Rule rule2 = new Rule( "test-rule2" );
+        rule2.setConsequence( this.consequence );
+        final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                        PropagationContext.ASSERTION,
+                                                                        rule2,
+                                                                        null );
+        final LeapsTuple tuple2 = new LeapsTuple( tuple2Handles,
+                                                  leapsRule1,
+                                                  context2 );
+        this.workingMemory.assertTuple( tuple2 );
+        // "logical" should only appear once
+        final Activation activation2 = this.workingMemory.getAgenda().getActivations()[1];
+        //
+        final String logicalString2 = new String( "logical" );
+        final FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+                                                                           false,
+                                                                           true,
+                                                                           rule2,
+                                                                           activation2 );
+
+        assertEquals( 3,
+                      this.workingMemory.getObjects().size() );
+        //
+        this.workingMemory.retractObject( tuple1Fact );
+        // check "logical" is still in the system
+        assertEquals( 2,
+                      this.workingMemory.getObjects().size() );
+
+        // now remove that final justification
+        this.workingMemory.retractObject( tuple2Fact );
+        // "logical" fact should no longer be in the system
+        assertEquals( 0,
+                      this.workingMemory.getObjects().size() );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,203 @@
+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.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.PackageIntegrationException;
+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.rule.Column;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.MockField;
+
+/** 
+ *  
+ * @author Alexander Bagerman
+ * 
+ */
+public class QueryResultsTest extends TestCase {
+    public void testQueryTerminalNode() throws PackageIntegrationException {
+        final LeapsRuleBase ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        final ClassObjectType cheeseObjectType = new ClassObjectType( Cheese.class );
+        final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator( Operator.EQUAL );
+        // fires on context.state == integer(1)
+        final Query query = new Query( "query-1" );
+
+        final Column cheeseColumn = new Column( 0,
+                                                cheeseObjectType,
+                                                "cheese" );
+        cheeseColumn.addConstraint( getLiteralConstraint( cheeseColumn,
+                                                          "type",
+                                                          "stilton",
+                                                          evaluator ) );
+        query.addPattern( cheeseColumn );
+
+        ruleBase.addRule( query );
+
+        final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+
+        workingMemory.fireAllRules();
+
+        LeapsQueryResults results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertNull( results );
+
+        final Cheese stilton1 = new Cheese( "stilton",
+                                            100 );
+
+        final FactHandle handle1 = workingMemory.assertObject( stilton1 );
+
+        workingMemory.fireAllRules();
+
+        results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        final Cheese cheddar = new Cheese( "cheddar",
+                                           55 );
+        workingMemory.assertObject( cheddar );
+
+        workingMemory.fireAllRules();
+
+        results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        final Cheese stilton2 = new Cheese( "stilton",
+                                            5 );
+
+        final FactHandle handle2 = workingMemory.assertObject( stilton2 );
+
+        workingMemory.fireAllRules();
+
+        results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 2,
+                      results.size() );
+
+        LeapsQueryResult result = (LeapsQueryResult) results.get( 0 );
+
+        assertEquals( 1,
+                      result.size() );
+
+        boolean wasStilton1 = (stilton1 == result.get( 0 ));
+
+        // assertSame( stilton1, result.get( 0 ) );
+
+        result = (LeapsQueryResult) results.get( 1 );
+
+        boolean wasStilton2 = (stilton2 == result.get( 0 ));
+
+        assertEquals( 1,
+                      result.size() );
+
+        // assertSame( stilton2, result.get( 0 ) );
+        assertTrue( (wasStilton1 && wasStilton2) || (!wasStilton1 && !wasStilton2) );
+        Object result1 = null, result2 = null;
+        int i = 0;
+        for ( final Iterator it = results.iterator(); it.hasNext(); ) {
+            result = (LeapsQueryResult) it.next();
+            assertEquals( 1,
+                          result.size() );
+            if ( i == 0 ) {
+                result1 = result.get( 0 );
+            } else {
+                result2 = result.get( 0 );
+            }
+            i++;
+        }
+        wasStilton1 = (stilton1 == result1);
+        wasStilton2 = (stilton2 == result2);
+        assertTrue( (wasStilton1 && wasStilton2) || (!wasStilton1 && !wasStilton2) );
+
+        workingMemory.retractObject( handle1 );
+
+        workingMemory.fireAllRules();
+
+        results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertEquals( 1,
+                      results.size() );
+
+        workingMemory.retractObject( handle2 );
+
+        workingMemory.fireAllRules();
+
+        results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+        assertNull( results );
+    }
+
+    public class Cheese {
+        private String type;
+
+        private int    price;
+
+        public Cheese(final String type,
+                      final int price) {
+            super();
+            this.type = type;
+            this.price = price;
+        }
+
+        public int getPrice() {
+            return this.price;
+        }
+
+        public String getType() {
+            return this.type;
+        }
+
+        public String toString() {
+            return "[Cheese type='" + this.type + "' price='" + this.price + "']";
+        }
+
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+                                                          final String fieldName,
+                                                          final Object fieldValue,
+                                                          final Evaluator evaluator) {
+        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 );
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,172 @@
+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 org.drools.DroolsTestCase;
+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.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+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 QueryTest extends DroolsTestCase {
+    LeapsRuleBase   ruleBase;
+    LeapsRuleBase   ruleBaseAddRule;
+
+    WorkingMemory   wm1;
+
+    // leaps add rule objects
+    final String    handle1Rule1    = "11";
+
+    final String    handle1Rule2    = "12";
+
+    final String    handle2Rule1    = "21";
+
+    final String    handle2Rule2    = "22";
+
+    final ArrayList handlesForRules = new ArrayList();
+
+    WorkingMemory   workingMemory;
+
+    Rule            rule1;
+
+    Rule            rule2;
+
+    final Context   context1        = new Context( 1 );
+
+    final Context   context2        = new Context( 1 );
+
+    public void setUp() throws Exception {
+        this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        this.wm1 = this.ruleBase.newWorkingMemory();
+        // add rules section
+        this.ruleBaseAddRule = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        this.workingMemory = this.ruleBaseAddRule.newWorkingMemory();
+        // rules
+        final ClassObjectType contextType = new ClassObjectType( Context.class );
+        final Evaluator integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+        // rule 1
+        // fires on context.state == integer(1)
+        this.rule1 = new Query( "query-to-execute" );
+        final Column contextColumnRule1 = new Column( 0,
+                                                      contextType,
+                                                      "context1" );
+        contextColumnRule1.addConstraint( getLiteralConstraint( contextColumnRule1,
+                                                                "state",
+                                                                new Integer( 1 ),
+                                                                integerEqualEvaluator ) );
+        this.rule1.addPattern( contextColumnRule1 );
+
+        this.rule2 = new Rule( "rule2" );
+        final Column contextColumnRule2 = new Column( 0,
+                                                      contextType,
+                                                      "context2" );
+        contextColumnRule2.addConstraint( getLiteralConstraint( contextColumnRule2,
+                                                                "state",
+                                                                new Integer( 1 ),
+                                                                integerEqualEvaluator ) );
+        this.rule2.addPattern( contextColumnRule2 );
+        final Declaration contextRule2Declaration = this.rule2.getDeclaration( "context2" );
+        this.rule2.setConsequence( new Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -5839841224218714327L;
+
+            public void evaluate(final KnowledgeHelper drools,
+                                 final WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    final Rule rule = drools.getRule();
+                    final Tuple tuple = drools.getTuple();
+
+                    final Context dummy = (Context) drools.get( contextRule2Declaration );
+                    if ( dummy == QueryTest.this.context1 ) {
+                        QueryTest.this.handlesForRules.add( QueryTest.this.handle1Rule2 );
+                    } else if ( dummy == QueryTest.this.context2 ) {
+                        QueryTest.this.handlesForRules.add( QueryTest.this.handle2Rule2 );
+                    }
+
+                } catch ( final Exception e ) {
+                    throw new ConsequenceException( e );
+                }
+            }
+
+        } );
+    }
+
+    public void testAddRuleBeforeFacts() throws Exception {
+
+        assertEquals( 0,
+                      this.handlesForRules.size() );
+
+        this.ruleBaseAddRule.addRule( this.rule1 );
+        this.ruleBaseAddRule.addRule( this.rule2 );
+        this.workingMemory.assertObject( this.context1 );
+        this.workingMemory.assertObject( this.context2 );
+        // firing
+        this.workingMemory.fireAllRules();
+        // finally everything should be filled
+        assertEquals( 2,
+                      this.handlesForRules.size() );
+        assertEquals( 2,
+                      this.workingMemory.getQueryResults( "query-to-execute" ).size() );
+        assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+        assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+    }
+
+    private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+                                                          final String fieldName,
+                                                          final Object fieldValue,
+                                                          final Evaluator evaluator) {
+        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 );
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,177 @@
+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.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.Duration;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class SchedulerTest extends DroolsTestCase {
+    public void testScheduledActivation() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+
+        final Rule rule = new Rule( "scheduled-test-rule" );
+        final List data = new ArrayList();
+
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -1991405634414239175L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                data.add( "tested" );
+            }
+        } );
+
+        /* 1/10th of a second */
+        final Duration duration = new Duration() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -1650013015631329969L;
+
+            public long getDuration(Tuple tuple) {
+                return 100;
+            }
+        };
+        rule.setDuration( duration );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        final LeapsFactHandle tupleFactHandle = (LeapsFactHandle) workingMemory.assertObject( "tuple object" );
+        final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
+        factHandlesTuple[0] = tupleFactHandle;
+
+        final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+        final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
+                                                 (LeapsRule) leapsRules.get( 0 ),
+                                                 context );
+
+        assertEquals( 0,
+                      data.size() );
+
+        workingMemory.assertTuple( tuple );
+
+        // sleep for 2 seconds
+        Thread.sleep( 300 );
+
+        // now check for update
+        assertEquals( 1,
+                      data.size() );
+    }
+
+    public void testDoLoopScheduledActivation() throws Exception {
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+        final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+
+        final Rule rule = new Rule( "do-loop-scheduled-test-rule" );
+        final List data = new ArrayList();
+
+        /* 1/10th of a second */
+        final Duration duration = new Duration() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = -65249353062404118L;
+
+            public long getDuration(Tuple tuple) {
+                return 100;
+            }
+        };
+
+        rule.setDuration( duration );
+
+        // add consequence
+        rule.setConsequence( new org.drools.spi.Consequence() {
+            /**
+             * 
+             */
+            private static final long serialVersionUID = 5431138295939934840L;
+
+            public void evaluate(final KnowledgeHelper knowledgeHelper,
+                                 final WorkingMemory workingMemory) {
+                /* on first invoke add another one to the agenda */
+                if ( data.size() < 3 ) {
+                    final PropagationContext context2 = new PropagationContextImpl( 0,
+                                                                                    0,
+                                                                                    rule,
+                                                                                    knowledgeHelper.getActivation() );
+
+                    final LeapsFactHandle tupleFactHandleIn = (LeapsFactHandle) workingMemory.assertObject( "tuple object in" );
+                    final LeapsFactHandle[] factHandlesTupleIn = new LeapsFactHandle[1];
+                    factHandlesTupleIn[0] = tupleFactHandleIn;
+                    final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+                    final LeapsTuple tupleIn = new LeapsTuple( factHandlesTupleIn,
+                                                               (LeapsRule) leapsRules.get( 0 ),
+                                                               context2 );
+                    ((LeapsWorkingMemory) workingMemory).assertTuple( tupleIn );
+                }
+                data.add( "tested" );
+            }
+        } );
+
+        final PropagationContext context = new PropagationContextImpl( 0,
+                                                                       PropagationContext.ASSERTION,
+                                                                       rule,
+                                                                       null );
+
+        final LeapsFactHandle tupleFactHandle = (LeapsFactHandle) workingMemory.assertObject( "tuple object" );
+        final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
+        factHandlesTuple[0] = tupleFactHandle;
+
+        final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+        final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
+                                                 (LeapsRule) leapsRules.get( 0 ),
+                                                 context );
+
+        workingMemory.assertTuple( tuple );
+
+        assertEquals( 0,
+                      data.size() );
+
+        // sleep for 0.5 seconds
+        Thread.sleep( 1000 );
+
+        // now check for update
+        assertEquals( 4,
+                      data.size() );
+
+    }
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,355 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.leaps.conflict.LoadOrderConflictResolver;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableIteratorTest extends TestCase {
+
+    DefaultFactHandle h1;
+
+    DefaultFactHandle h1000;
+
+    DefaultFactHandle h100;
+
+    DefaultFactHandle h10;
+
+    Table             testTable;
+
+    protected void setUp() {
+        this.testTable = new Table( LoadOrderConflictResolver.getInstance() );
+        this.h1 = new DefaultFactHandle( 1,
+                                         "1" );
+        this.h1000 = new DefaultFactHandle( 1000,
+                                            "1000" );
+        this.h100 = new DefaultFactHandle( 100,
+                                           "100" );
+        this.h10 = new DefaultFactHandle( 10,
+                                          "10" );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools..util.TableIterator.TableIterator()'
+     */
+    public void testTableIterator() {
+        final IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( null,
+                                                                                          null );
+        assertFalse( it.hasNext() );
+        assertTrue( it.isEmpty() );
+    }
+
+    public void testGetDominantFactIterator() {
+        final Iterator it = Table.singleItemIterator( this.h1000 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1000 );
+        assertFalse( it.hasNext() );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools..util.TableIterator.TableIterator(TableRecord)'
+     */
+    public void testTableIteratorTableRecord() {
+        final IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertTrue( it.hasNext() );
+        assertFalse( it.isEmpty() );
+        assertEquals( this.h1,
+                      it.next() );
+        assertFalse( it.hasNext() );
+        assertFalse( it.isEmpty() );
+
+    }
+
+    /*
+     * Test method for
+     * 'org.drools..util.TableIterator.TableIterator(TableRecord,
+     * TableRecord, TableRecord)'
+     */
+    public void testTableIteratorTableRecordTableRecordTableRecord() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertTrue( it.hasNext() );
+        assertFalse( it.isEmpty() );
+        assertEquals( this.h1,
+                      it.next() );
+        assertFalse( it.hasNext() );
+        assertFalse( it.isEmpty() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertFalse( it.isEmpty() );
+        assertTrue( it.hasNext() );
+        assertEquals( this.h1000,
+                      it.next() );
+        assertTrue( it.hasNext() );
+        assertEquals( this.h100,
+                      it.next() );
+        assertTrue( it.hasNext() );
+        assertEquals( this.h10,
+                      it.next() );
+        assertTrue( it.hasNext() );
+        assertEquals( this.h1,
+                      it.next() );
+        assertFalse( it.hasNext() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        assertFalse( it.isEmpty() );
+        assertTrue( it.hasNext() );
+        assertTrue( it.hasNext() );
+        assertEquals( this.h1,
+                      it.next() );
+        assertFalse( it.hasNext() );
+
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.isEmpty()'
+     */
+    public void testIsEmpty() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertFalse( it.isEmpty() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertFalse( it.isEmpty() );
+        it = new IteratorFromPositionToTableStart( this.testTable.tailRecord,
+                                                   this.testTable.headRecord );
+        assertFalse( it.isEmpty() );
+        it = new IteratorFromPositionToTableStart( null,
+                                                   null );
+        assertTrue( it.isEmpty() );
+
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.reset()'
+     */
+    public void testReset() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.next() );
+        it.reset();
+        assertEquals( this.h1,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertEquals( this.h1000,
+                      it.next() );
+        it.reset();
+        assertEquals( this.h1000,
+                      it.next() );
+        it.next();
+        it.next();
+        it.reset();
+        assertEquals( this.h1000,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        it.reset();
+        assertEquals( this.h1000,
+                      it.next() );
+        it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertEquals( this.h1,
+                      it.next() );
+        it.reset();
+        assertEquals( this.h1,
+                      it.next() );
+
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.hasNext()'
+     */
+    public void testHasNext() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertTrue( it.hasNext() );
+        assertFalse( it.isEmpty() );
+        assertEquals( this.h1,
+                      it.next() );
+        assertFalse( it.hasNext() );
+        assertFalse( it.isEmpty() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertTrue( it.hasNext() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        assertTrue( it.hasNext() );
+        it = new IteratorFromPositionToTableStart( null,
+                                                   null );
+        assertFalse( it.hasNext() );
+        it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertTrue( it.hasNext() );
+
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.next()'
+     */
+    public void testNext() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertEquals( this.h1000,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.next() );
+        it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertEquals( this.h1,
+                      it.next() );
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.current()'
+     */
+    public void testCurrent() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertEquals( this.h1000,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.next() );
+        it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertEquals( this.h1,
+                      it.next() );
+    }
+
+    /*
+     * Test method for 'org.drools..util.TableIterator.peekNext()'
+     */
+    public void testPeekNext() {
+        this.testTable.add( this.h1 );
+        IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                                                    this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.peekNext() );
+        assertEquals( this.h1,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.headRecord );
+        assertEquals( this.h1000,
+                      it.peekNext() );
+        assertEquals( this.h1000,
+                      it.next() );
+        this.testTable.clear();
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h10 );
+        this.testTable.add( this.h100 );
+        it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+                                                   this.testTable.tailRecord );
+        assertEquals( this.h1,
+                      it.peekNext() );
+        assertEquals( this.h1,
+                      it.next() );
+        it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+        assertEquals( this.h1,
+                      it.peekNext() );
+        assertEquals( this.h1,
+                      it.next() );
+
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,54 @@
+package org.drools.leaps.util;
+
+/*
+ * 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 junit.framework.TestCase;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableRecordTest extends TestCase {
+
+    public void testConstractor() {
+        final String object = new String( "test object" );
+        final TableRecord record = new TableRecord( object );
+        assertEquals( object,
+                      record.object );
+    }
+
+    public void testLeft() {
+        final String object1 = new String( "test object1" );
+        final String object2 = new String( "test object2" );
+        final TableRecord record1 = new TableRecord( object1 );
+        final TableRecord record2 = new TableRecord( object2 );
+        record1.left = record2;
+        assertEquals( object2,
+                      record1.left.object );
+    }
+
+    public void testRight() {
+        final String object1 = new String( "test object1" );
+        final String object2 = new String( "test object2" );
+        final TableRecord record1 = new TableRecord( object1 );
+        final TableRecord record2 = new TableRecord( object2 );
+        record1.right = record2;
+        assertEquals( object2,
+                      record1.right.object );
+    }
+
+}
\ No newline at end of file

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,256 @@
+package org.drools.leaps.util;
+
+/*
+ * 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.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.examples.manners.Context;
+import org.drools.examples.manners.Guest;
+import org.drools.examples.manners.Hobby;
+import org.drools.examples.manners.Sex;
+import org.drools.leaps.conflict.LoadOrderConflictResolver;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableTest extends TestCase {
+
+    DefaultFactHandle h1;
+
+    DefaultFactHandle h1000;
+
+    DefaultFactHandle h100;
+
+    DefaultFactHandle h10;
+
+    Table             testTable;
+
+    protected void setUp() {
+        this.testTable = new Table( LoadOrderConflictResolver.getInstance() );
+        this.h1 = new DefaultFactHandle( 1,
+                                         "1" );
+        this.h1000 = new DefaultFactHandle( 1000,
+                                            "1000" );
+        this.h100 = new DefaultFactHandle( 100,
+                                           "100" );
+        this.h10 = new DefaultFactHandle( 10,
+                                          "10" );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.add(Object)'
+     */
+    public void testAddAndContains() {
+        assertFalse( this.testTable.contains( this.h1 ) );
+        this.testTable.add( this.h1 );
+        assertTrue( this.testTable.contains( this.h1 ) );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.remove(Object)'
+     */
+    public void testRemove() {
+        assertFalse( this.testTable.contains( this.h1 ) );
+        this.testTable.add( this.h1 );
+        assertTrue( this.testTable.contains( this.h1 ) );
+        this.testTable.remove( this.h1 );
+        assertFalse( this.testTable.contains( this.h1 ) );
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        assertTrue( this.testTable.contains( this.h100 ) );
+        this.testTable.remove( this.h100 );
+        assertFalse( this.testTable.contains( this.h100 ) );
+        assertTrue( this.testTable.contains( this.h1000 ) );
+        this.testTable.remove( this.h1000 );
+        assertFalse( this.testTable.contains( this.h1000 ) );
+        assertTrue( this.testTable.contains( this.h1 ) );
+        this.testTable.remove( this.h1 );
+        assertFalse( this.testTable.contains( this.h1 ) );
+        final Iterator it = this.testTable.iterator();
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h10 );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.isEmpty()'
+     */
+    public void testIsEmpty() {
+        assertTrue( this.testTable.isEmpty() );
+        this.testTable.add( this.h1 );
+        assertFalse( this.testTable.isEmpty() );
+        this.testTable.remove( this.h1 );
+        assertTrue( this.testTable.isEmpty() );
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        assertFalse( this.testTable.isEmpty() );
+        this.testTable.remove( this.h100 );
+        assertFalse( this.testTable.isEmpty() );
+        this.testTable.remove( this.h1000 );
+        assertFalse( this.testTable.isEmpty() );
+        this.testTable.remove( this.h1 );
+        assertFalse( this.testTable.isEmpty() );
+        this.testTable.remove( this.h10 );
+        assertTrue( this.testTable.isEmpty() );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.headObject'
+     */
+    public void testHeadObject() {
+        this.testTable.add( this.h1 );
+        assertEquals( this.h1,
+                      this.testTable.headRecord.object );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        assertEquals( this.h1000,
+                      this.testTable.headRecord.object );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.tailObject'
+     */
+    public void testTailObject() {
+        this.testTable.add( this.h1 );
+        assertEquals( this.testTable.tailRecord.object,
+                      this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        assertEquals( this.testTable.tailRecord.object,
+                      this.h1 );
+    }
+
+    /*
+     * Test method for 'org.drools..util.Table.iterator()'
+     */
+    public void testIterator() {
+        Iterator it;
+        // empty iterator
+        it = this.testTable.iterator();
+        assertFalse( it.hasNext() );
+        // iterate over a single element
+        this.testTable.add( this.h1 );
+        it = this.testTable.iterator();
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1 );
+        assertFalse( it.hasNext() );
+        // several items iterator
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        it = this.testTable.iterator();
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1000 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h100 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h10 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1 );
+        assertFalse( it.hasNext() );
+    }
+
+    public void testTailIterator() {
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+
+        TableIterator it = this.testTable.iteratorFromPositionToTableStart( this.h100,
+                                                                            this.h10 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h10 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1 );
+        assertFalse( it.hasNext() );
+        it.reset();
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h100 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h10 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1 );
+        assertFalse( it.hasNext() );
+
+        this.testTable.clear();
+        final DefaultFactHandle fh1 = new DefaultFactHandle( 1,
+                                                             new Guest( "1",
+                                                                        Sex.resolve( "m" ),
+                                                                        Hobby.resolve( "h2" ) ) );
+        final DefaultFactHandle fh2 = new DefaultFactHandle( 2,
+                                                             new Guest( "1",
+                                                                        Sex.resolve( "m" ),
+                                                                        Hobby.resolve( "h1" ) ) );
+        final DefaultFactHandle fh3 = new DefaultFactHandle( 3,
+                                                             new Guest( "1",
+                                                                        Sex.resolve( "m" ),
+                                                                        Hobby.resolve( "h3" ) ) );
+        final DefaultFactHandle fh4 = new DefaultFactHandle( 4,
+                                                             new Guest( "3",
+                                                                        Sex.resolve( "f" ),
+                                                                        Hobby.resolve( "h2" ) ) );
+        final DefaultFactHandle fhC = new DefaultFactHandle( 5,
+                                                             new Context( "start" ) );
+        this.testTable.add( fh1 );
+        this.testTable.add( fh2 );
+        this.testTable.add( fh3 );
+        this.testTable.add( fh4 );
+        it = this.testTable.iteratorFromPositionToTableStart( fhC,
+                                                              fhC );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      fh4 );
+    }
+
+    public void testHeadIterator() {
+        this.testTable.add( this.h1 );
+        this.testTable.add( this.h1000 );
+        this.testTable.add( this.h100 );
+        this.testTable.add( this.h10 );
+        final TableIterator it = this.testTable.iteratorFromPositionToTableEnd( this.h1 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h10 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h100 );
+        assertTrue( it.hasNext() );
+        assertEquals( it.next(),
+                      this.h1000 );
+        assertFalse( it.hasNext() );
+    }
+}

Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java	2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java	2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,312 @@
+package org.drools.leaps.util;
+
+import junit.framework.TestCase;
+
+import org.drools.leaps.LeapsFactHandle;
+import org.drools.leaps.Token;
+
+public class TokenStackTest extends TestCase {
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.empty()'
+     */
+    public void testEmpty() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Token token = new Token( null,
+                                       new LeapsFactHandle( 3,
+                                                            new Object() ),
+                                       null );
+        stack.push( token );
+        assertFalse( stack.empty() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.peek()'
+     */
+    public void testPeek() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Object object = new Object();
+        final Token token1 = new Token( null,
+                                        new LeapsFactHandle( 1,
+                                                             object ),
+                                        null );
+        stack.push( token1 );
+        final Token token2 = new Token( null,
+                                        new LeapsFactHandle( 2,
+                                                             object ),
+                                        null );
+        stack.push( token2 );
+        final Token token10 = new Token( null,
+                                         new LeapsFactHandle( 10,
+                                                              object ),
+                                         null );
+        stack.push( token10 );
+        final Token token8 = new Token( null,
+                                        new LeapsFactHandle( 8,
+                                                             object ),
+                                        null );
+        stack.push( token8 );
+        final Token token6 = new Token( null,
+                                        new LeapsFactHandle( 6,
+                                                             object ),
+                                        null );
+        stack.push( token6 );
+        final Token token3 = new Token( null,
+                                        new LeapsFactHandle( 3,
+                                                             object ),
+                                        null );
+        stack.push( token3 );
+        final Token token4 = new Token( null,
+                                        new LeapsFactHandle( 4,
+                                                             object ),
+                                        null );
+        stack.push( token4 );
+
+        assertEquals( token4,
+                      stack.peek() );
+        stack.pop();
+        assertEquals( token3,
+                      stack.peek() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.pop()'
+     */
+    public void testPop() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Object object = new Object();
+        final Token token1 = new Token( null,
+                                        new LeapsFactHandle( 1,
+                                                             object ),
+                                        null );
+        stack.push( token1 );
+        final Token token2 = new Token( null,
+                                        new LeapsFactHandle( 2,
+                                                             object ),
+                                        null );
+        stack.push( token2 );
+        final Token token10 = new Token( null,
+                                         new LeapsFactHandle( 10,
+                                                              object ),
+                                         null );
+        stack.push( token10 );
+        final Token token8 = new Token( null,
+                                        new LeapsFactHandle( 8,
+                                                             object ),
+                                        null );
+        stack.push( token8 );
+        final Token token6 = new Token( null,
+                                        new LeapsFactHandle( 6,
+                                                             object ),
+                                        null );
+        stack.push( token6 );
+        final Token token3 = new Token( null,
+                                        new LeapsFactHandle( 3,
+                                                             object ),
+                                        null );
+        stack.push( token3 );
+        final Token token4 = new Token( null,
+                                        new LeapsFactHandle( 4,
+                                                             object ),
+                                        null );
+        stack.push( token4 );
+
+        assertEquals( token4,
+                      stack.peek() );
+        stack.pop();
+        assertEquals( token3,
+                      stack.peek() );
+        stack.pop();
+        stack.pop();
+        stack.pop();
+        stack.pop();
+        stack.pop();
+        assertEquals( token1,
+                      stack.peek() );
+        stack.pop();
+
+        assertTrue( stack.empty() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+     */
+    public void testRemoveBottom() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Object object = new Object();
+        final Token token1 = new Token( null,
+                                        new LeapsFactHandle( 1,
+                                                             object ),
+                                        null );
+        stack.push( token1 );
+        final Token token2 = new Token( null,
+                                        new LeapsFactHandle( 2,
+                                                             object ),
+                                        null );
+        stack.push( token2 );
+        final Token token10 = new Token( null,
+                                         new LeapsFactHandle( 10,
+                                                              object ),
+                                         null );
+        stack.push( token10 );
+        final Token token8 = new Token( null,
+                                        new LeapsFactHandle( 8,
+                                                             object ),
+                                        null );
+        stack.push( token8 );
+        final Token token6 = new Token( null,
+                                        new LeapsFactHandle( 6,
+                                                             object ),
+                                        null );
+        stack.push( token6 );
+        final Token token3 = new Token( null,
+                                        new LeapsFactHandle( 3,
+                                                             object ),
+                                        null );
+        stack.push( token3 );
+        final Token token4 = new Token( null,
+                                        new LeapsFactHandle( 4,
+                                                             object ),
+                                        null );
+        stack.push( token4 );
+
+        stack.remove( 1 );
+        assertEquals( token4,
+                      stack.peek() );
+        stack.pop();
+        assertEquals( token3,
+                      stack.peek() );
+        stack.pop();
+        stack.pop();
+        stack.pop();
+        stack.pop();
+        stack.pop();
+
+        assertTrue( stack.empty() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+     */
+    public void testRemoveTop() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Object object = new Object();
+        final Token token1 = new Token( null,
+                                        new LeapsFactHandle( 1,
+                                                             object ),
+                                        null );
+        stack.push( token1 );
+        final Token token2 = new Token( null,
+                                        new LeapsFactHandle( 2,
+                                                             object ),
+                                        null );
+        stack.push( token2 );
+        final Token token10 = new Token( null,
+                                         new LeapsFactHandle( 10,
+                                                              object ),
+                                         null );
+        stack.push( token10 );
+        final Token token8 = new Token( null,
+                                        new LeapsFactHandle( 8,
+                                                             object ),
+                                        null );
+        stack.push( token8 );
+        final Token token6 = new Token( null,
+                                        new LeapsFactHandle( 6,
+                                                             object ),
+                                        null );
+        stack.push( token6 );
+        final Token token3 = new Token( null,
+                                        new LeapsFactHandle( 3,
+                                                             object ),
+                                        null );
+        stack.push( token3 );
+        final Token token4 = new Token( null,
+                                        new LeapsFactHandle( 4,
+                                                             object ),
+                                        null );
+        stack.push( token4 );
+
+        stack.remove( 4 );
+        assertEquals( token3,
+                      stack.pop() );
+        assertEquals( token6,
+                      stack.pop() );
+        assertEquals( token8,
+                      stack.pop() );
+        assertEquals( token10,
+                      stack.pop() );
+        assertEquals( token2,
+                      stack.pop() );
+        assertEquals( token1,
+                      stack.pop() );
+
+        assertTrue( stack.empty() );
+    }
+
+    /*
+     * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+     */
+    public void testRemoveMiddle() {
+        final TokenStack stack = new TokenStack();
+        assertTrue( stack.empty() );
+        final Object object = new Object();
+        final Token token1 = new Token( null,
+                                        new LeapsFactHandle( 1,
+                                                             object ),
+                                        null );
+        stack.push( token1 );
+        final Token token2 = new Token( null,
+                                        new LeapsFactHandle( 2,
+                                                             object ),
+                                        null );
+        stack.push( token2 );
+        final Token token10 = new Token( null,
+                                         new LeapsFactHandle( 10,
+                                                              object ),
+                                         null );
+        stack.push( token10 );
+        final Token token8 = new Token( null,
+                                        new LeapsFactHandle( 8,
+                                                             object ),
+                                        null );
+        stack.push( token8 );
+        final Token token6 = new Token( null,
+                                        new LeapsFactHandle( 6,
+                                                             object ),
+                                        null );
+        stack.push( token6 );
+        final Token token3 = new Token( null,
+                                        new LeapsFactHandle( 3,
+                                                             object ),
+                                        null );
+        stack.push( token3 );
+        final Token token4 = new Token( null,
+                                        new LeapsFactHandle( 4,
+                                                             object ),
+                                        null );
+        stack.push( token4 );
+
+        stack.remove( 10 );
+        assertEquals( token4,
+                      stack.pop() );
+        assertEquals( token3,
+                      stack.pop() );
+        assertEquals( token6,
+                      stack.pop() );
+        assertEquals( token8,
+                      stack.pop() );
+        assertEquals( token2,
+                      stack.pop() );
+        assertEquals( token1,
+                      stack.pop() );
+
+        assertTrue( stack.empty() );
+    }
+
+}




More information about the jboss-svn-commits mailing list