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

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Sat Aug 19 01:27:47 EDT 2006


Author: bagerman
Date: 2006-08-19 01:27:40 -0400 (Sat, 19 Aug 2006)
New Revision: 5945

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java
Log:
>From constraint
Deftemplate
Hashing table now used for Not and Exists table scans

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/ColumnConstraints.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -20,7 +20,6 @@
 import java.util.List;
 
 import org.drools.WorkingMemory;
-import org.drools.base.ClassObjectType;
 import org.drools.common.BetaNodeBinder;
 import org.drools.common.InternalFactHandle;
 import org.drools.rule.Column;
@@ -34,7 +33,7 @@
  * 
  */
 public class ColumnConstraints implements Serializable {
-    private Class                   classType;
+    private Object                  classType;
 
     private final FieldConstraint[] alphaConstraints;
 
@@ -47,7 +46,7 @@
     public ColumnConstraints(final Column column,
                              final List alpha,
                              final BetaNodeBinder beta) {
-        this.classType = ((ClassObjectType) column.getObjectType()).getClassType();
+        this.classType = LeapsBuilder.getLeapsClassType( column.getObjectType() );
 
         if ( beta != null ) {
             this.beta = beta;
@@ -65,7 +64,7 @@
         }
     }
 
-    protected final Class getClassType() {
+    protected final Object getClassType() {
         return this.classType;
     }
 
@@ -111,5 +110,12 @@
     protected final boolean isAlphaPresent() {
         return this.alphaPresent;
     }
-
+    
+    protected FieldConstraint[] getAlphaContraints() {
+        return this.alphaConstraints;
+    }
+    
+    protected FieldConstraint[] getBetaContraints() {
+        return this.beta.getConstraints( );
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FactTable.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -16,13 +16,17 @@
  * limitations under the License.
  */
 
+import java.util.Comparator;
 import java.util.Iterator;
-import java.util.LinkedList;
 
 import org.drools.common.DefaultFactHandle;
 import org.drools.common.PropagationContextImpl;
+import org.drools.leaps.util.IteratorFromPositionToTableStart;
 import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
 import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.IdentityMap;
 
 /**
  * Implementation of a container to store data elements used throughout the
@@ -53,7 +57,7 @@
      * Tuples that are either already on agenda or are very close (missing
      * exists or have not facts matching)
      */
-    private LinkedList        tuples;
+    private final IdentityMap tuples;
 
     /**
      * initializes base LeapsTable with appropriate Comparator and positive and
@@ -65,7 +69,9 @@
     public FactTable(final ConflictResolver conflictResolver) {
         super( conflictResolver.getFactConflictResolver( ) );
         this.rules = new RuleTable( conflictResolver.getRuleConflictResolver( ) );
-        this.tuples = new LinkedList( );
+        this.tuples = new IdentityMap();
+        this.comparator = conflictResolver.getFactConflictResolver( );
+        this.notAndExistsHashedTables = new IdentityMap( );
     }
 
     /**
@@ -92,15 +98,12 @@
                             final LeapsRuleHandle ruleHandle ) {
         this.rules.remove( ruleHandle );
         // remove tuples that are still there
-        final LinkedList list = new LinkedList( );
-
         for (final Iterator it = this.getTuplesIterator( ); it.hasNext( );) {
             final LeapsTuple tuple = (LeapsTuple) it.next( );
-            if (ruleHandle.getLeapsRule( ).getRule( ) != tuple.getLeapsRule( ).getRule( )) {
-                list.add( tuple );
+            if (ruleHandle.getLeapsRule( ).getRule( ) == tuple.getLeapsRule( ).getRule( )) {
+                this.tuples.remove( tuple );
             }
         }
-        this.tuples = list;
     }
 
     /**
@@ -167,7 +170,7 @@
 
         ret.append( "\nTuples :" );
 
-        for (final Iterator it = this.tuples.iterator( ); it.hasNext( );) {
+        for (final Iterator it = this.tuples.values( ).iterator( ); it.hasNext( );) {
             ret.append( "\n" + it.next( ) );
         }
 
@@ -183,10 +186,74 @@
     }
 
     protected Iterator getTuplesIterator() {
-        return this.tuples.iterator( );
+        return this.tuples.values( ).iterator( );
     }
 
     protected void addTuple( final LeapsTuple tuple ) {
-        this.tuples.add( tuple );
+        this.tuples.put( tuple,tuple );
     }
+
+    protected void removeTuple( final LeapsTuple tuple ) {
+        this.tuples.remove( tuple );
+    }
+
+    
+    private final IdentityMap notAndExistsHashedTables;
+
+    private final Comparator  comparator;
+    
+    public void add( Object object ) {
+        super.add( object );
+        for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
+            ((HashedTableComponent)it.next( )).add( (LeapsFactHandle)object );
+        }
+    }
+
+    public void remove( Object object ) {
+        super.remove( object );
+        for (Iterator it = this.notAndExistsHashedTables.values( ).iterator( ); it.hasNext( );) {
+            ((HashedTableComponent)it.next( )).remove( (LeapsFactHandle)object );
+        }
+    }
+
+    protected void createHashedSubTable(ColumnConstraints constraint) {
+        this.notAndExistsHashedTables.put( constraint, new HashedTableComponent( constraint,
+                        this.comparator ) );
+    }
+
+    protected TableIterator reverseOrderIterator( Tuple tuple, ColumnConstraints constraint ) {
+        TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).reverseOrderIterator( tuple ); 
+        if (ret == null){
+            ret = Table.emptyIterator( );
+        }
+        return ret;
+    }
+
+    protected TableIterator iteratorFromPositionToTableStart( Tuple tuple,
+                                                              ColumnConstraints constraint,
+                                                              LeapsFactHandle startFactHandle,
+                                                              LeapsFactHandle currentFactHandle ) {
+        TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).iteratorFromPositionToTableStart( tuple,
+                                                                                                                                         startFactHandle,
+                                                                                                                                         currentFactHandle );
+        if (ret == null) {
+            ret = Table.emptyIterator( );
+        }
+        return ret;
+    }
+
+    protected TableIterator iteratorFromPositionToTableEnd( Tuple tuple,
+                                                            ColumnConstraints constraint,
+                                                            LeapsFactHandle startFactHandle ) {
+        TableIterator ret = ( (HashedTableComponent) this.notAndExistsHashedTables.get( constraint ) ).iteratorFromPositionToTableEnd( tuple,
+                                                                                                                                       startFactHandle );
+        if (ret == null) {
+            ret = Table.emptyIterator( );
+        }
+        return ret;
+    }
+    
+    protected Iterator getHashedConstraints(){
+        return this.notAndExistsHashedTables.keySet( ).iterator( );
+    }
 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/FromConstraint.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,25 @@
+package org.drools.leaps;
+
+import java.util.Arrays;
+
+import org.drools.common.BetaNodeBinder;
+import org.drools.rule.Column;
+import org.drools.spi.DataProvider;
+
+public class FromConstraint extends ColumnConstraints {
+    private final DataProvider provider;
+
+    public FromConstraint(Column column,
+            DataProvider provider,
+            ColumnConstraints constraints) {
+        super( column,
+               ( constraints.getAlphaContraints( ) == null || constraints.getAlphaContraints( ).length == 0 ) ? Arrays.asList( new FromConstraint[0] )
+                       : Arrays.asList( constraints.getAlphaContraints( ) ),
+               new BetaNodeBinder( constraints.getBetaContraints( ) ) );
+        this.provider = provider;
+    }
+
+    public DataProvider getProvider() {
+        return provider;
+    }
+}

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/HashedTableComponent.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,162 @@
+package org.drools.leaps;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.base.evaluators.Operator;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.Declaration;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Tuple;
+
+public class HashedTableComponent implements Serializable{
+    private final ColumnConstraints constraints;
+
+    private final int               numberOfVariableConstraints;
+
+    private final Map               buckets;
+
+    private final Comparator        comparator;
+
+    private final static Integer    DEFAULT_HASH = new Integer( 0 );
+    
+    private final Table noConstraintsTable;
+
+    public HashedTableComponent(ColumnConstraints constraints, Comparator comparator) {
+        this.constraints = constraints;
+        this.comparator = comparator;
+        this.buckets = new HashMap( );
+        this.numberOfVariableConstraints = this.constraints.getBetaContraints( ).length;
+        this.noConstraintsTable = new Table(this.comparator);
+    }
+
+    public void add( LeapsFactHandle factHandle ) {
+        Table table = this.getTable( factHandle, true );
+        if (table != null) {
+            table.add( factHandle );
+        }
+    }
+
+    public void remove( LeapsFactHandle factHandle ) {
+        Table table = this.getTable( factHandle, false );
+        if (table != null) {
+            table.remove( factHandle );
+        }
+    }
+
+    public TableIterator reverseOrderIterator( Tuple tuple ) {
+        Table table = this.getTable( tuple );
+        if (table != null) {
+            return table.reverseOrderIterator( );
+        }
+        else {
+            return null;
+        }
+    }
+
+    public TableIterator iteratorFromPositionToTableEnd( Tuple tuple,
+                                                           LeapsFactHandle startFactHandle ) {
+        Table table = this.getTable( tuple );
+        if (table != null) {
+            return table.iteratorFromPositionToTableEnd( startFactHandle );
+        }
+        else {
+            return null;
+        }
+    }
+
+    public TableIterator iteratorFromPositionToTableStart( Tuple tuple,
+                                                           LeapsFactHandle startFactHandle,
+                                                           LeapsFactHandle currentFactHandle ) {
+        Table table = this.getTable( tuple );
+        if (table != null) {
+            return table.iteratorFromPositionToTableStart( startFactHandle,
+                                                           currentFactHandle );
+        }
+        else {
+            return null;
+        }
+    }
+
+    private Table getTable( Tuple tuple ) {
+        Table ret = null;
+        if (this.numberOfVariableConstraints > 0) {
+            Map currentMap = this.buckets;
+            for (int i = 0; ( i < this.numberOfVariableConstraints )
+                    && ( currentMap != null ); i++) {
+                Integer hash = DEFAULT_HASH;
+                if (this.constraints.getBetaContraints( )[i] instanceof VariableConstraint
+                        && ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getEvaluator( )
+                                                                                            .getOperator( ) == Operator.EQUAL) {
+                    Declaration declaration = this.constraints.getBetaContraints( )[i].getRequiredDeclarations( )[0];
+                    final Object select = declaration.getValue( tuple.get( declaration.getColumn( )
+                                                                                      .getFactIndex( ) )
+                                                                     .getObject( ) );
+                    if (select != null) {
+                        hash = new Integer( select.hashCode( ) );
+                    }
+                }
+                // put facts at the very bottom / last instance
+                if (i != ( this.numberOfVariableConstraints - 1 )) {
+                    // we can not have null as a value to the key
+                    currentMap = (Map) currentMap.get( hash );
+                }
+                else {
+                    ret = (Table) currentMap.get( hash );
+                }
+            }
+        }
+        else {
+            ret = this.noConstraintsTable;
+        }
+        return ret;
+    }
+
+    private Table getTable( LeapsFactHandle factHandle, boolean createIfNotThere ) {
+        Table ret = null;
+        Map currentMap = this.buckets;
+        if (this.constraints.isAllowedAlpha( factHandle, null, null )) {
+            if (this.numberOfVariableConstraints > 0) {
+                for (int i = 0; ( i < this.numberOfVariableConstraints )
+                        && ( currentMap != null ); i++) {
+                    Integer hash = DEFAULT_HASH;
+                    if (this.constraints.getBetaContraints( )[i] instanceof VariableConstraint
+                            && ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getEvaluator( )
+                                                                                                .getOperator( ) == Operator.EQUAL) {
+                        final Object select = ( (VariableConstraint) this.constraints.getBetaContraints( )[i] ).getFieldExtractor( )
+                                                                                                               .getValue( factHandle.getObject( ) );
+                        if (select != null) {
+                            hash = new Integer( select.hashCode( ) );
+                        }
+                    }
+                    // put facts at the very bottom / last instance
+                    if (i != ( this.numberOfVariableConstraints - 1 )) {
+                        // we can not have null as a value to the key
+                        Map map = (Map) currentMap.get( hash );
+                        if (map == null && createIfNotThere) {
+                            map = new HashMap( );
+                            currentMap.put( hash, map );
+                        }
+                        currentMap = map;
+                    }
+                    else {
+                        Table table = (Table) currentMap.get( hash );
+                        if (table == null && createIfNotThere) {
+                            table = new Table( this.comparator );
+                            currentMap.put( hash, table );
+                        }
+                        ret = table;
+                    }
+                }
+            }
+            else {
+                return this.noConstraintsTable;
+            }
+        }
+        return ret;
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsAgenda.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -55,6 +55,7 @@
                                                                                     .isEmpty( ) )) {
                 // fire regular rule
                 super.fireActivation( activation );
+                ((LeapsTuple)activation.getTuple( )).setWasFired( true );
                 if (activation.getRule( ).getActivationGroup( ) != null) {
                     this.getActivationGroup( activation.getRule( ).getActivationGroup( ) );
                 }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsBuilder.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,259 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.base.ClassObjectType;
+import org.drools.common.BetaNodeBinder;
+import org.drools.facttemplates.FactTemplate;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.rule.And;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Exists;
+import org.drools.rule.From;
+import org.drools.rule.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Not;
+import org.drools.rule.Rule;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.ObjectType;
+
+/**
+ * A Rule<code>Builder</code> to process <code>Rule</code>s for use with
+ * Leaps WorkingMemories. Produces list of Leaps rules that wrap Rule and can be
+ * used in Leaps algorithm. All methods are static
+ * 
+ * @author Alexander Bagerman
+ * 
+ */
+class LeapsBuilder {
+    /**
+     * follows RETEOO logic flow but returns leaps rules list
+     * 
+     * @param rule
+     * @return list of leaps rule
+     * @throws InvalidPatternException
+     */
+    final protected static List processRule(final Rule rule) throws InvalidPatternException {
+        final ArrayList leapsRules = new ArrayList();
+        final And[] and = rule.getTransformedLhs();
+        for ( int i = 0, length = and.length; i < length; i++ ) {
+            leapsRules.addAll( processRuleForAnd( and[i],
+                                                  rule ) );
+        }
+        return leapsRules;
+    }
+
+    /**
+     * Creates list of leaps rules for each individual And
+     * 
+     * @param and
+     * @param rule
+     * @return list of leaps rules for the given And
+     */
+    final private static List processRuleForAnd(final And and,
+                                                final Rule rule) {
+        ColumnConstraints constraints;
+        final ArrayList leapsRules = new ArrayList();
+        final ArrayList cols = new ArrayList();
+        final ArrayList notCols = new ArrayList();
+        final ArrayList existsCols = new ArrayList();
+        final ArrayList evalConditions = new ArrayList();
+        for ( final Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
+            final Object object = it.next();
+            if ( object instanceof EvalCondition ) {
+                final EvalCondition eval = (EvalCondition) object;
+                evalConditions.add( eval );
+            } else {
+                if ( object instanceof Column ) {
+                    constraints = LeapsBuilder.processColumn( (Column) object  );
+                    // create column constraints
+                } else if ( object instanceof From ){
+                    constraints = LeapsBuilder.processColumn( ((From) object).getColumn( )  );
+                }
+                else {
+                    // NOTS and EXISTS
+                    GroupElement ce = (GroupElement) object;
+                    while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
+                        ce = (GroupElement) ce.getChildren().get( 0 );
+                    }
+                    constraints = LeapsBuilder.processColumn( (Column) ce.getChildren().get( 0 )  );
+                }
+                if (object.getClass( ) == Not.class) {
+                    notCols.add( constraints );
+                }
+                else if (object.getClass( ) == Exists.class) {
+                    existsCols.add( constraints );
+                }
+                else if (object.getClass( ) == From.class) {
+                    cols.add( new FromConstraint(((From)object).getColumn( ), ((From)object).getDataProvider( ), constraints ));
+                }       
+                else {
+                    cols.add( constraints );
+                }
+            }
+        }
+
+        // check eval for presence of required declarations
+        checkEvalUnboundDeclarations( rule,
+                                      evalConditions );
+        //
+        leapsRules.add( new LeapsRule( rule,
+                                       cols,
+                                       notCols,
+                                       existsCols,
+                                       evalConditions) );
+
+        return leapsRules;
+    }
+
+    /**
+     * Make sure the required declarations are previously bound
+     * 
+     * @param declarations
+     * @throws InvalidPatternException
+     */
+    static void checkEvalUnboundDeclarations(final Rule rule,
+                                             final ArrayList evals) throws InvalidPatternException {
+        final List list = new ArrayList();
+        for ( final Iterator it = evals.iterator(); it.hasNext(); ) {
+            final EvalCondition ec = (EvalCondition) it.next();
+            final Declaration[] declarations = ec.getRequiredDeclarations();
+            for ( int i = 0, length = declarations.length; i < length; i++ ) {
+                if ( rule.getDeclaration( declarations[i].getIdentifier() ) == null ) {
+                    list.add( declarations[i].getIdentifier() );
+                }
+            }
+        }
+
+        // Make sure the required declarations
+        if ( list.size() != 0 ) {
+            final StringBuffer buffer = new StringBuffer();
+            buffer.append( list.get( 0 ) );
+            for ( int i = 1, size = list.size(); i < size; i++ ) {
+                buffer.append( ", " + list.get( i ) );
+            }
+
+            throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+        }
+    }
+
+    /**
+     * extracts column specific constraints and packages it into
+     * <code>ColumnConstraints</code>
+     * 
+     * @param column
+     * @param and
+     * @return leaps packaged ColumnConstraints
+     */
+    final private static ColumnConstraints processColumn(final Column column ) {
+        BetaNodeBinder binder;
+        final List alphaConstraints = new ArrayList( );
+        final List predicateConstraints = new ArrayList( );
+
+        final List constraints = column.getConstraints( );
+
+        Map declarations = new HashMap( );
+
+        if (column.getDeclaration( ) != null) {
+            final Declaration declaration = column.getDeclaration( );
+            // Add the declaration the map of previously bound declarations
+            declarations.put( declaration.getIdentifier( ), declaration );
+        }
+
+        for (final Iterator it = constraints.iterator( ); it.hasNext( );) {
+            final Object object = it.next( );
+            // Check if its a declaration
+            if (object instanceof Declaration) {
+                final Declaration declaration = (Declaration) object;
+                // Add the declaration the map of previously bound declarations
+                declarations.put( declaration.getIdentifier( ), declaration );
+                continue;
+            }
+
+            final FieldConstraint fieldConstraint = (FieldConstraint) object;
+            if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+                alphaConstraints.add( fieldConstraint);
+            } else {
+                predicateConstraints.add( fieldConstraint );
+            }
+        }
+
+        if ( !predicateConstraints.isEmpty() ) {
+            binder = new BetaNodeBinder( (FieldConstraint[]) predicateConstraints.toArray( new FieldConstraint[predicateConstraints.size()] ) );
+        } else {
+            binder = new BetaNodeBinder();
+        }
+
+        return new ColumnConstraints( column,
+                                      alphaConstraints,
+                                      binder );
+    }
+    /**
+     * Make sure the required declarations are previously bound
+     * 
+     * @param declarations
+     * @throws InvalidPatternException
+     */
+    private static void checkUnboundDeclarations(final Map declarations, final Declaration[] requiredDeclarations) throws InvalidPatternException {
+        final List list = new ArrayList();
+        for ( int i = 0, length = requiredDeclarations.length; i < length; i++ ) {
+            if ( declarations.get( requiredDeclarations[i].getIdentifier() ) == null ) {
+                list.add( requiredDeclarations[i].getIdentifier() );
+            }
+        }
+
+        // Make sure the required declarations        
+        if ( list.size() != 0 ) {
+            final StringBuffer buffer = new StringBuffer();
+            buffer.append( list.get( 0 ) );
+            for ( int i = 1, size = list.size(); i < size; i++ ) {
+                buffer.append( ", " + list.get( i ) );
+            }
+
+            throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+        }
+
+    }
+    
+    public static Object getLeapsClassType(Object o) {
+        if(o instanceof org.drools.facttemplates.Fact) {
+           return ((org.drools.facttemplates.Fact)o).getFactTemplate( ).getName( );
+        }
+        else {
+            return o.getClass( );
+        }
+    }
+    
+    public static Object getLeapsClassType(ObjectType ot) {
+        if(ot.getClass( ) == FactTemplateObjectType.class) {
+            return ((FactTemplateObjectType) ot).getFactTemplate( ).getName( );
+        }
+        else {
+            // we assume that it's classobject type
+            return ((ClassObjectType) ot).getClassType();
+        }
+    }
+
+}
\ No newline at end of file

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRule.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -50,28 +50,28 @@
     final Class[]             existsNotsClasses;
 
     public LeapsRule(final Rule rule,
-                     final ArrayList columns,
-                     final ArrayList notColumns,
-                     final ArrayList existsColumns,
-                     final ArrayList evalConditions) {
+            final ArrayList columns,
+            final ArrayList notColumns,
+            final ArrayList existsColumns,
+            final ArrayList evalConditions) {
         this.rule = rule;
         this.columnConstraints = (ColumnConstraints[]) columns.toArray( new ColumnConstraints[0] );
         this.notColumnConstraints = (ColumnConstraints[]) notColumns.toArray( new ColumnConstraints[0] );
         this.existsColumnConstraints = (ColumnConstraints[]) existsColumns.toArray( new ColumnConstraints[0] );
         this.evalConditions = (EvalCondition[]) evalConditions.toArray( new EvalCondition[0] );
-        this.notColumnsPresent = (this.notColumnConstraints.length != 0);
-        this.existsColumnsPresent = (this.existsColumnConstraints.length != 0);
-        this.evalCoditionsPresent = (this.evalConditions.length != 0);
+        this.notColumnsPresent = ( this.notColumnConstraints.length != 0 );
+        this.existsColumnsPresent = ( this.existsColumnConstraints.length != 0 );
+        this.evalCoditionsPresent = ( this.evalConditions.length != 0 );
 
-        final ArrayList classes = new ArrayList();
-        for ( int i = 0; i < this.notColumnConstraints.length; i++ ) {
-            if ( !classes.contains( this.notColumnConstraints[i].getClassType() ) ) {
-                classes.add( this.notColumnConstraints[i].getClassType() );
+        final ArrayList classes = new ArrayList( );
+        for (int i = 0; i < this.notColumnConstraints.length; i++) {
+            if (!classes.contains( this.notColumnConstraints[i].getClassType( ) )) {
+                classes.add( this.notColumnConstraints[i].getClassType( ) );
             }
         }
-        for ( int i = 0; i < this.existsColumnConstraints.length; i++ ) {
-            if ( !classes.contains( this.existsColumnConstraints[i].getClassType() ) ) {
-                classes.add( this.existsColumnConstraints[i].getClassType() );
+        for (int i = 0; i < this.existsColumnConstraints.length; i++) {
+            if (!classes.contains( this.existsColumnConstraints[i].getClassType( ) )) {
+                classes.add( this.existsColumnConstraints[i].getClassType( ) );
             }
         }
 
@@ -98,11 +98,11 @@
         return this.evalConditions.length;
     }
 
-    Class getColumnClassObjectTypeAtPosition(final int idx) {
-        return this.columnConstraints[idx].getClassType();
+    Object getColumnClassObjectTypeAtPosition( final int idx ) {
+        return this.columnConstraints[idx].getClassType( );
     }
 
-    ColumnConstraints getColumnConstraintsAtPosition(final int idx) {
+    ColumnConstraints getColumnConstraintsAtPosition( final int idx ) {
         return this.columnConstraints[idx];
     }
 
@@ -131,10 +131,10 @@
     }
 
     public int hashCode() {
-        return this.rule.hashCode();
+        return this.rule.hashCode( );
     }
 
-    public boolean equals(final Object that) {
+    public boolean equals( final Object that ) {
         return this == that;
     }
 
@@ -153,7 +153,7 @@
         return this.agendaGroup;
     }
 
-    public void setAgendaGroup(final AgendaGroupImpl agendaGroup) {
+    public void setAgendaGroup( final AgendaGroupImpl agendaGroup ) {
         this.agendaGroup = agendaGroup;
     }
-}
\ No newline at end of file
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsRuleBase.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -127,7 +127,7 @@
                                         InvalidPatternException {
         super.addRule( rule );
 
-        final List rules = Builder.processRule( rule );
+        final List rules = LeapsBuilder.processRule( rule );
 
         this.leapsRules.put( rule,
                              rules );

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsTuple.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -48,8 +48,9 @@
 
     private Activation             activation;
 
-    private final LeapsRule        leapsRule;
+    private final LeapsRule         leapsRule;
 
+    private boolean                 wasFired               = false;
     /**
      * agendaItem parts
      */
@@ -272,4 +273,12 @@
     protected void setContext(final PropagationContext context) {
         this.context = context;
     }
+
+    public boolean isWasFired() {
+        return wasFired;
+    }
+
+    public void setWasFired( boolean wasFired ) {
+        this.wasFired = wasFired;
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/LeapsWorkingMemory.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -67,218 +67,234 @@
  * @see java.io.Serializable
  * 
  */
-class LeapsWorkingMemory extends AbstractWorkingMemory
-    implements
-    EventSupport,
-    PropertyChangeListener {
+class LeapsWorkingMemory extends AbstractWorkingMemory implements EventSupport,
+        PropertyChangeListener {
     private static final long serialVersionUID       = 320;
 
     private final Map         queryResults;
 
-    private final IdentityMap leapsRulesToHandlesMap = new IdentityMap();
+    private final IdentityMap leapsRulesToHandlesMap = new IdentityMap( );
 
-    private final IdentityMap rulesActivationsMap    = new IdentityMap();
+    private final IdentityMap rulesActivationsMap    = new IdentityMap( );
 
+    private final LinkedList  noPositiveColumnsRules = new LinkedList( );
+
     /**
      * Construct.
      * 
      * @param ruleBase
      *            The backing rule-base.
      */
-    public LeapsWorkingMemory(final int id,
-                              final InternalRuleBase ruleBase) {
-        super( id,
-               ruleBase,
-               ruleBase.newFactHandleFactory() );
-        this.queryResults = new HashMap();
+    public LeapsWorkingMemory(final int id, final InternalRuleBase ruleBase) {
+        super( id, ruleBase, ruleBase.newFactHandleFactory( ) );
+        this.queryResults = new HashMap( );
         this.agenda = new LeapsAgenda( this );
     }
 
-    public void doAssertObject(final InternalFactHandle factHandle,
-                               final Object object,
-                               final PropagationContext propagationContext) throws FactException {
+    public void doAssertObject( final InternalFactHandle factHandle,
+                                final Object object,
+                                final PropagationContext propagationContext )
+            throws FactException {
 
-        this.pushTokenOnStack( factHandle,
-                               new Token( this,
-                                          factHandle,
-                                          propagationContext ) );
+        this.pushTokenOnStack( factHandle, new Token( this, factHandle, propagationContext ) );
 
         // determine what classes it belongs to put it into the "table" on
         // class name key
-        final Class objectClass = object.getClass();
-        for ( final Iterator tables = this.getFactTablesList( objectClass ).iterator(); tables.hasNext(); ) {
-            final FactTable factTable = (FactTable) tables.next();
+        List tuplesToAssert = new LinkedList( );
+        final Object objectClass = LeapsBuilder.getLeapsClassType( object );
+        for (final Iterator tables = this.getFactTablesList( objectClass ).iterator( ); tables.hasNext( );) {
+            tuplesToAssert.clear( );
+            final FactTable factTable = (FactTable) tables.next( );
             // adding fact to container
             factTable.add( factHandle );
-            // inspect all tuples for exists and not conditions and activate
-            // /
-            // deactivate agenda items
-            for ( final Iterator tuples = factTable.getTuplesIterator(); tuples.hasNext(); ) {
-                final LeapsTuple tuple = (LeapsTuple) tuples.next();
-                boolean tupleWasReadyForActivation = tuple.isReadyForActivation();
-                if ( !tuple.isActivationNull() ) {
-                    // check not constraints only on activated tuples to see
-                    // if
-                    // we need to deactivate
-                    final ColumnConstraints[] not = tuple.getLeapsRule().getNotColumnConstraints();
-                    for ( int i = 0, length = not.length; i < length; i++ ) {
-                        final ColumnConstraints constraint = not[i];
-                        if ( !tuple.isBlockingNotFactHandle( i ) && constraint.getClassType().isAssignableFrom( objectClass ) && constraint.isAllowed( factHandle,
-                                                                                                                                                       tuple,
-                                                                                                                                                       this ) ) {
-                            tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle,
-                                                            i );
-                            ((LeapsFactHandle) factHandle).addNotTuple( tuple,
-                                                                        i );
-                        }
+            for (final Iterator tuples = factTable.getTuplesIterator( ); tuples.hasNext( );) {
+                final LeapsTuple tuple = (LeapsTuple) tuples.next( );
+
+                final ColumnConstraints[] not = tuple.getLeapsRule( )
+                                                     .getNotColumnConstraints( );
+                for (int i = 0, length = not.length; i < length; i++) {
+                    final ColumnConstraints constraint = not[i];
+                    final Object columnClassObject = constraint.getClassType( );
+                    if (!tuple.isBlockingNotFactHandle( i )
+                            && ( ( objectClass.getClass( ) == Class.class
+                                    && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+                                    && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+                            && constraint.isAllowed( factHandle, tuple, this )) {
+                        tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
+                        ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
                     }
-                    // check and see if we need de-activate
-                    if ( !tuple.isReadyForActivation() ) {
-                        if ( tuple.getLeapsRule().getRule() instanceof Query ) {
-                            // put query results to the working memory
-                            // location
-                            removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
-                                                    tuple );
-                        } else {
-                            // time to pull from agenda
-                            invalidateActivation( tuple );
-                        }
+                }
+                // check exists constraints and activate constraints
+                final ColumnConstraints[] exists = tuple.getLeapsRule( )
+                                                        .getExistsColumnConstraints( );
+                for (int i = 0, length = exists.length; i < length; i++) {
+                    final ColumnConstraints constraint = exists[i];
+                    final Object columnClassObject = constraint.getClassType( );
+                    if (!tuple.isExistsFactHandle( i )
+                            && ( ( objectClass.getClass( ) == Class.class
+                                    && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+                                    && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+                            && constraint.isAllowed( factHandle, tuple, this )) {
+                        tuple.setExistsFactHandle( (LeapsFactHandle) factHandle, i );
+                        ( (LeapsFactHandle) factHandle ).addExistsTuple( tuple, i );
                     }
-                } else {
-                    // check exists constraints and activate constraints
-                    final ColumnConstraints[] exists = tuple.getLeapsRule().getExistsColumnConstraints();
-                    for ( int i = 0, length = exists.length; i < length; i++ ) {
-                        final ColumnConstraints constraint = exists[i];
-                        if ( !tuple.isExistsFactHandle( i ) && constraint.getClassType().isAssignableFrom( objectClass ) && constraint.isAllowed( factHandle,
-                                                                                                                                                  tuple,
-                                                                                                                                                  this ) ) {
-                            tuple.setExistsFactHandle( (LeapsFactHandle) factHandle,
-                                                       i );
-                            ((LeapsFactHandle) factHandle).addExistsTuple( tuple,
-                                                                           i );
-                        }
+                }
+                // check and see if we need activate
+                // activate only if tuple was not ready for it before
+                if (tuple.isReadyForActivation( )) {
+                    // ready to activate
+                    tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
+                                                                  PropagationContext.ASSERTION,
+                                                                  tuple.getLeapsRule( )
+                                                                       .getRule( ),
+                                                                  null ) );
+                    tuplesToAssert.add( tuple );
+                }
+            }
+            for (Iterator tuples = tuplesToAssert.iterator( ); tuples.hasNext( );) {
+                LeapsTuple tuple = (LeapsTuple) tuples.next( );
+                factTable.removeTuple( tuple );
+                this.assertTuple( tuple );
+            }
+        }
+        // inspect all tuples for exists and not conditions and activate
+        // deactivate agenda items
+        Activation[] activations = this.agenda.getActivations( );
+        for (int k = 0; k < activations.length; k++) {
+            boolean deActivate = false;
+            LeapsTuple tuple = (LeapsTuple) activations[k].getTuple( );
+            final ColumnConstraints[] not = tuple.getLeapsRule( ).getNotColumnConstraints( );
+            for (int i = 0, length = not.length; i < length; i++) {
+                final ColumnConstraints constraint = not[i];
+                final Object columnClassObject = constraint.getClassType( );
+                if (!tuple.isBlockingNotFactHandle( i ) 
+                        && ( ( objectClass.getClass( ) == Class.class
+                                && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) ) || ( objectClass.getClass( ) != Class.class
+                                && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) ) )
+                        && constraint.isAllowed( factHandle, tuple, this )) {
+                    tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle, i );
+                    ( (LeapsFactHandle) factHandle ).addNotTuple( tuple, i );
+                    if (!deActivate) {
+                        deActivate = true;
                     }
-                    // check and see if we need activate
-                    // activate only if tuple was not ready for it before
-                    if ( !tupleWasReadyForActivation && tuple.isReadyForActivation() ) {
-                        // ready to activate
-                        tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
-                                                                      PropagationContext.ASSERTION,
-                                                                      tuple.getLeapsRule().getRule(),
-                                                                      null ) );
-
-                        this.assertTuple( tuple );
-                    }
                 }
             }
+            // check and see if we need de-activate
+            if (deActivate) {
+                if (tuple.getLeapsRule( ).getRule( ) instanceof Query) {
+                    // put query results to the working memory
+                    // location
+                    removeFromQueryResults( tuple.getLeapsRule( ).getRule( ).getName( ),
+                                            tuple );
+                }
+                else {
+                    // time to pull from agenda
+                    invalidateActivation( tuple );
+                }
+            }
         }
     }
 
     /**
-     * copies reteoo behaviour in regards to logical assertion 
-     * and does checking on available tuples to see if any needs
-     * invalidation / activation as a result of this retraction
+     * copies reteoo behaviour in regards to logical assertion and does checking
+     * on available tuples to see if any needs invalidation / activation as a
+     * result of this retraction
      * 
      * @see WorkingMemory
      */
-    public void doRetract(final InternalFactHandle factHandle,
-                          final PropagationContext propagationContext) {
+    public void doRetract( final InternalFactHandle factHandle,
+                           final PropagationContext propagationContext ) {
 
         /*
          * leaps specific actions
          */
         // remove fact from all relevant fact tables container
-        for ( final Iterator it = this.getFactTablesList( factHandle.getObject().getClass() ).iterator(); it.hasNext(); ) {
-            ((FactTable) it.next()).remove( factHandle );
+        for (final Iterator it = this.getFactTablesList( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
+                                     .iterator( ); it.hasNext( );) {
+            ( (FactTable) it.next( ) ).remove( factHandle );
         }
 
         // 0. remove activated tuples
-        final Iterator tuples = ((LeapsFactHandle) factHandle).getActivatedTuples();
-        for ( ; tuples != null && tuples.hasNext(); ) {
-            final LeapsTuple tuple = (LeapsTuple) tuples.next();
-            if ( tuple.getLeapsRule().getRule() instanceof Query ) {
+        final Iterator tuples = ( (LeapsFactHandle) factHandle ).getActivatedTuples( );
+        for (; tuples != null && tuples.hasNext( );) {
+            final LeapsTuple tuple = (LeapsTuple) tuples.next( );
+            if (tuple.getLeapsRule( ).getRule( ) instanceof Query) {
                 // put query results to the working memory location
-                removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
-                                        tuple );
-            } else {
+                removeFromQueryResults( tuple.getLeapsRule( ).getRule( ).getName( ), tuple );
+            }
+            else {
                 // time to pull from agenda
                 invalidateActivation( tuple );
             }
         }
 
         // 1. remove fact for nots and exists tuples
-        final IdentityMap tuplesNotReadyForActivation = new IdentityMap();
+        final IdentityMap tuplesNotReadyForActivation = new IdentityMap( );
         FactHandleTupleAssembly assembly;
         LeapsTuple tuple;
         Iterator it;
-        it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
-        if ( it != null ) {
-            for ( ; it.hasNext(); ) {
-                assembly = (FactHandleTupleAssembly) it.next();
-                tuple = assembly.getTuple();
-                if ( !tuple.isReadyForActivation() ) {
-                    tuplesNotReadyForActivation.put( tuple,
-                                                     tuple );
+        it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
+        if (it != null) {
+            for (; it.hasNext( );) {
+                assembly = (FactHandleTupleAssembly) it.next( );
+                tuple = assembly.getTuple( );
+                if (!tuple.isReadyForActivation( )) {
+                    tuplesNotReadyForActivation.put( tuple, tuple );
                 }
-                tuple.removeBlockingNotFactHandle( assembly.getIndex() );
+                tuple.removeBlockingNotFactHandle( assembly.getIndex( ) );
 
                 TokenEvaluator.evaluateNotCondition( (LeapsFactHandle) factHandle,
-                                                     //                                                                          TokenEvaluator.evaluateNotCondition( new LeapsFactHandle( factHandle.getRecency( ) + 1,
-                                                     //                                                                                                                                    new Object( ) ),
-                                                     assembly.getIndex(),
+                // TokenEvaluator.evaluateNotCondition( new LeapsFactHandle(
+                // factHandle.getRecency( ) + 1,
+                                                     // new Object( ) ),
+                                                     assembly.getIndex( ),
                                                      tuple,
                                                      this );
             }
         }
-        it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
-        if ( it != null ) {
-            for ( ; it.hasNext(); ) {
-                assembly = (FactHandleTupleAssembly) it.next();
-                tuple = assembly.getTuple();
-                if ( !tuple.isReadyForActivation() ) {
-                    tuplesNotReadyForActivation.put( tuple,
-                                                     tuple );
+        it = ( (LeapsFactHandle) factHandle ).getExistsTupleAssemblies( );
+        if (it != null) {
+            for (; it.hasNext( );) {
+                assembly = (FactHandleTupleAssembly) it.next( );
+                tuple = assembly.getTuple( );
+                if (!tuple.isReadyForActivation( )) {
+                    tuplesNotReadyForActivation.put( tuple, tuple );
                 }
-                tuple.removeExistsFactHandle( assembly.getIndex() );
+                tuple.removeExistsFactHandle( assembly.getIndex( ) );
                 TokenEvaluator.evaluateExistsCondition( (LeapsFactHandle) factHandle,
-                                                        //                                                                             TokenEvaluator.evaluateExistsCondition( new LeapsFactHandle( factHandle.getRecency( ) + 1,
-                                                        //                                                                                                                                          null ),
-                                                        assembly.getIndex(),
+                // TokenEvaluator.evaluateExistsCondition( new LeapsFactHandle(
+                // factHandle.getRecency( ) + 1,
+                                                        // null ),
+                                                        assembly.getIndex( ),
                                                         tuple,
                                                         this );
             }
         }
         // 2. assert all tuples that are ready for activation or cancel ones
         // that are no longer
-        final IteratorChain chain = new IteratorChain();
-        it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
-        if ( it != null ) {
+        final IteratorChain chain = new IteratorChain( );
+        it = ( (LeapsFactHandle) factHandle ).getNotTupleAssemblies( );
+        if (it != null) {
             chain.addIterator( it );
         }
-        it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
-        if ( it != null ) {
+        it = ( (LeapsFactHandle) factHandle ).getExistsTupleAssemblies( );
+        if (it != null) {
             chain.addIterator( it );
         }
-        for ( ; chain.hasNext(); ) {
-            tuple = ((FactHandleTupleAssembly) chain.next()).getTuple();
+        for (; chain.hasNext( );) {
+            tuple = ( (FactHandleTupleAssembly) chain.next( ) ).getTuple( );
             // can assert only tuples that were not eligible for activation
             // before retraction
-            if ( tuple.isReadyForActivation() && tuple.isActivationNull() && tuplesNotReadyForActivation.containsKey( tuple ) ) {
+            if (tuple.isReadyForActivation( )) {
                 // ready to activate
-                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+                tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter( ),
                                                               PropagationContext.ASSERTION,
-                                                              tuple.getLeapsRule().getRule(),
+                                                              tuple.getLeapsRule( )
+                                                                   .getRule( ),
                                                               null ) );
+                this.getFactTable( LeapsBuilder.getLeapsClassType( factHandle.getObject( ) ) )
+                    .removeTuple( tuple );
                 this.assertTuple( tuple );
-            } else {
-                if ( tuple.getLeapsRule().getRule() instanceof Query ) {
-                    // put query results to the working memory location
-                    removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
-                                            tuple );
-                } else {
-                    // time to pull from agenda
-                    invalidateActivation( tuple );
-                }
             }
         }
 
@@ -287,80 +303,81 @@
     }
 
     /**
-     * used when assertion / retraction adds invalidating conditions that 
-     * make tuple ineligible for firing
+     * used when assertion / retraction adds invalidating conditions that make
+     * tuple ineligible for firing
      * 
      * @param tuple
      */
-    private final void invalidateActivation(final LeapsTuple tuple) {
-        final Activation activation = tuple.getActivation();
-        if ( !tuple.isReadyForActivation() && !tuple.isActivationNull() ) {
+    private final void invalidateActivation( final LeapsTuple tuple ) {
+        final Activation activation = tuple.getActivation( );
+        if (!tuple.isReadyForActivation( ) && !tuple.isActivationNull( )) {
             // invalidate agenda agendaItem
-            if ( activation.isActivated() ) {
-                activation.remove();
-                getAgendaEventSupport().fireActivationCancelled( activation );
+            if (activation.isActivated( )) {
+                activation.remove( );
+                getAgendaEventSupport( ).fireActivationCancelled( activation );
             }
             //
             tuple.setActivation( null );
         }
-        if ( activation != null ) {
+        if (activation != null) {
             // remove logical dependency
             this.tms.removeLogicalDependencies( activation,
-                                                tuple.getContext(),
-                                                tuple.getLeapsRule().getRule() );
+                                                tuple.getContext( ),
+                                                tuple.getLeapsRule( ).getRule( ) );
 
             // remove from rule / activaitons map
-            FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule() );
-            if ( activations != null ) {
+            FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule( ) );
+            if (activations != null) {
                 activations.remove( activation );
             }
         }
     }
 
     /**
-     * modify is implemented as half way retract / assert due to the truth maintenance issues.
+     * modify is implemented as half way retract / assert due to the truth
+     * maintenance issues.
      * 
      * @see WorkingMemory
      */
-    public void modifyObject(final FactHandle factHandle,
-                             final Object object,
-                             final Rule rule,
-                             final Activation activation) throws FactException {
+    public void modifyObject( final FactHandle factHandle,
+                              final Object object,
+                              final Rule rule,
+                              final Activation activation ) throws FactException {
         try {
-            this.getLock().lock();
+            this.getLock( ).lock( );
             final PropagationContext propagationContext = new PropagationContextImpl( this.propagationIdCounter++,
                                                                                       PropagationContext.MODIFICATION,
                                                                                       rule,
                                                                                       activation );
 
-            final int status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
+            final int status = ( (InternalFactHandle) factHandle ).getEqualityKey( )
+                                                                  .getStatus( );
 
             final Object originalObject = this.assertMap.remove( factHandle );
-            if ( originalObject == null ) {
+            if (originalObject == null) {
                 throw new NoSuchFactObjectException( factHandle );
             }
             // 
             // do subset of retractObject( )
             //
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
-            if ( handle.getId() == -1 ) {
+            if (handle.getId( ) == -1) {
                 // can't retract an already retracted handle
                 return;
             }
             removePropertyChangeListener( handle );
 
-            doRetract( handle,
-                       propagationContext );
+            doRetract( handle, propagationContext );
 
             // Update the equality key, which maintains a list of stated
             // FactHandles
-            final EqualityKey key = handle.getEqualityKey();
+            final EqualityKey key = handle.getEqualityKey( );
 
             key.removeFactHandle( handle );
             handle.setEqualityKey( null );
 
             // If the equality key is now empty, then remove it
-            if ( key.isEmpty() ) {
+            if (key.isEmpty( )) {
                 this.tms.remove( key );
             }
             // produces NPE otherwise
@@ -370,23 +387,21 @@
             // and now assert
             //
             /* check to see if this is a logically asserted object */
-            this.assertObject( object,
-                               false,
-                               (status == EqualityKey.STATED) ? false : true,
-                               rule,
-                               activation );
+            this.assertObject( object, false, ( status == EqualityKey.STATED ) ? false
+                    : true, rule, activation );
 
             this.workingMemoryEventSupport.fireObjectModified( propagationContext,
                                                                handle,
-                                                               handle.getObject(),
+                                                               handle.getObject( ),
                                                                object );
 
-            if ( !this.factQueue.isEmpty() ) {
-                propagateQueuedActions();
+            if (!this.factQueue.isEmpty( )) {
+                propagateQueuedActions( );
             }
-        } finally {
-            this.getLock().unlock();
         }
+        finally {
+            this.getLock( ).unlock( );
+        }
     }
 
     /**
@@ -397,7 +412,7 @@
     /**
      * algorithm stack.
      */
-    private final TokenStack mainStack       = new TokenStack();
+    private final TokenStack mainStack       = new TokenStack( );
 
     /**
      * generates or just return List of internal factTables that correspond a
@@ -405,20 +420,25 @@
      * 
      * @return
      */
-    protected final List getFactTablesList(final Class c) {
-        final ArrayList list = new ArrayList();
-        // interfaces
-        final Class[] interfaces = c.getInterfaces();
-        for ( int i = 0; i < interfaces.length; i++ ) {
-            list.add( this.getFactTable( interfaces[i] ) );
+    protected final List getFactTablesList( final Object objectClass ) {
+        final ArrayList list = new ArrayList( );
+        if (objectClass.getClass( ) == Class.class) {
+            // interfaces
+            final Class[] interfaces = ( (Class) objectClass ).getInterfaces( );
+            for (int i = 0; i < interfaces.length; i++) {
+                list.add( this.getFactTable( interfaces[i] ) );
+            }
+            // classes
+            Class bufClass = (Class) objectClass;
+            while (bufClass != null) {
+                //
+                list.add( this.getFactTable( bufClass ) );
+                // and get the next class on the list
+                bufClass = bufClass.getSuperclass( );
+            }
         }
-        // classes
-        Class bufClass = c;
-        while ( bufClass != null ) {
-            //
-            list.add( this.getFactTable( bufClass ) );
-            // and get the next class on the list
-            bufClass = bufClass.getSuperclass();
+        else {
+            list.add( this.getFactTable( objectClass ) );
         }
         return list;
     }
@@ -426,30 +446,33 @@
     /**
      * adds new leaps token on main stack
      * 
-     * @param fact handle
+     * @param fact
+     *            handle
      * @param token
      */
-    protected final void pushTokenOnStack(final InternalFactHandle factHandle,
-                                          final Token token) {
+    protected final void pushTokenOnStack( final InternalFactHandle factHandle,
+                                           final Token token ) {
         this.mainStack.push( token );
     }
 
     /**
      * removes leaps token on main stack
      * 
-     * @param fact handle
+     * @param fact
+     *            handle
      */
-    protected final void removeTokenFromStack(final LeapsFactHandle factHandle) {
-        this.mainStack.remove( factHandle.getId() );
+    protected final void removeTokenFromStack( final LeapsFactHandle factHandle ) {
+        this.mainStack.remove( factHandle.getId( ) );
     }
 
     /**
      * gets leaps token from top of stack
      * 
-     * @param fact handle
+     * @param fact
+     *            handle
      */
     protected final Token peekTokenOnTop() {
-        return (Token) this.mainStack.peek();
+        return (Token) this.mainStack.peek( );
     }
 
     /**
@@ -459,24 +482,28 @@
      *            of objects
      * @return fact table of requested class type
      */
-    protected FactTable getFactTable(final Class c) {
+    protected FactTable getFactTable( final Object objectClass ) {
         FactTable table;
-        if ( this.factTables.containsKey( c ) ) {
-            table = (FactTable) this.factTables.get( c );
-        } else {
-            table = new FactTable( DefaultConflictResolver.getInstance() );
-            this.factTables.put( c,
-                                 table );
+        if (this.factTables.containsKey( objectClass )) {
+            table = (FactTable) this.factTables.get( objectClass );
+        }
+        else {
+            table = new FactTable( DefaultConflictResolver.getInstance( ) );
+            this.factTables.put( objectClass, table );
             // review existing rules and assign to the fact table if needed
-            for ( final Iterator iter = this.leapsRulesToHandlesMap.keySet().iterator(); iter.hasNext(); ) {
-                final LeapsRule leapsRule = (LeapsRule) iter.next();
-                if ( leapsRule.getNumberOfColumns() > 0 ) {
+            for (final Iterator iter = this.leapsRulesToHandlesMap.keySet( ).iterator( ); iter.hasNext( );) {
+                final LeapsRule leapsRule = (LeapsRule) iter.next( );
+                if (leapsRule.getNumberOfColumns( ) > 0) {
                     final List rulesHandles = (List) this.leapsRulesToHandlesMap.get( leapsRule );
-                    for ( final Iterator handles = rulesHandles.iterator(); handles.hasNext(); ) {
-                        final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next();
-                        if ( leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition() ).isAssignableFrom( c ) ) {
-                            table.addRule( this,
-                                           handle );
+                    for (final Iterator handles = rulesHandles.iterator( ); handles.hasNext( );) {
+                        final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next( );
+                        final Object columnClassObject = leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition( ) );
+                        if (( objectClass.getClass( ) == Class.class
+                                && columnClassObject.getClass( ) == Class.class && ( (Class) columnClassObject ).isAssignableFrom( (Class) objectClass ) )
+                                // on template name
+                                || ( objectClass.getClass( ) != Class.class
+                                        && columnClassObject.getClass( ) != Class.class && columnClassObject.equals( objectClass ) )) {
+                            table.addRule( this, handle );
                         }
                     }
                 }
@@ -491,142 +518,181 @@
      * 
      * @param rules
      */
-    protected void addLeapsRules(final List rules) {
-        this.getLock().lock();
+    protected void addLeapsRules( final List rules ) {
+        this.getLock( ).lock( );
         try {
             ArrayList ruleHandlesList;
             LeapsRule rule;
             LeapsRuleHandle ruleHandle;
-            for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
-                rule = (LeapsRule) it.next();
+            for (final Iterator it = rules.iterator( ); it.hasNext( );) {
+                rule = (LeapsRule) it.next( );
+                // create hashed entries for not and exists
+                // check for NOT and EXISTS and create new hashed entry
+                ColumnConstraints constraint;
+                for (int i = 0; i < rule.getNumberOfNotColumns( ); i++) {
+                    constraint = rule.getNotColumnConstraints( )[i];
+                    this.getFactTable( constraint.getClassType( ) )
+                        .createHashedSubTable( constraint );
+                }
+                for (int i = 0; i < rule.getNumberOfExistsColumns( ); i++) {
+                    constraint = rule.getExistsColumnConstraints( )[i];
+                    this.getFactTable( constraint.getClassType( ) )
+                        .createHashedSubTable( constraint );
+                }
                 // some times rules do not have "normal" constraints and only
                 // not and exists
-                if ( rule.getNumberOfColumns() > 0 ) {
-                    ruleHandlesList = new ArrayList();
-                    for ( int i = 0; i < rule.getNumberOfColumns(); i++ ) {
-                        ruleHandle = new LeapsRuleHandle( ((LeapsFactHandleFactory) this.handleFactory).getNextId(),
+                if (rule.getNumberOfColumns( ) > 0) {
+                    ruleHandlesList = new ArrayList( );
+                    for (int i = 0; i < rule.getNumberOfColumns( ); i++) {
+                        ruleHandle = new LeapsRuleHandle( ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( ),
                                                           rule,
                                                           i );
                         // 
-                        this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) ).addRule( this,
-                                                                                                   ruleHandle );
-                        //
+                        if (rule.getColumnConstraintsAtPosition( i ).getClass( ) != FromConstraint.class) {
+                            this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) )
+                                .addRule( this, ruleHandle );
+                            //
+                        }
+                        else {
+                            FactTable table = this.getFactTable( FromConstraintFactDriver.class );
+                            table.addRule( this, ruleHandle );
+                            if (table.isEmpty( )) {
+                                this.assertObject( new FromConstraintFactDriver( ) );
+                            }
+                        }
                         ruleHandlesList.add( ruleHandle );
                     }
-                    this.leapsRulesToHandlesMap.put( rule,
-                                                     ruleHandlesList );
-                } else {
-                    // to pick up rules that do not require columns, only not
-                    // and exists
-                    final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter(),
-                                                                                       PropagationContext.ASSERTION,
-                                                                                       null,
-                                                                                       null );
-
-                    TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
-                                                                                        rule,
-                                                                                        context ),
-                                                                        rule,
-                                                                        this );
+                    this.leapsRulesToHandlesMap.put( rule, ruleHandlesList );
                 }
+                else {
+                    this.noPositiveColumnsRules.add( new LeapsRuleHandle( ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( ),
+                                                                          rule,
+                                                                          0 ) );
+                }
             }
-        } finally {
-            this.getLock().unlock();
         }
+        finally {
+            this.getLock( ).unlock( );
+        }
     }
 
-    protected void removeRule(final List rules) {
-        this.getLock().lock();
+    protected void removeRule( final List rules ) {
+        this.getLock( ).lock( );
         try {
             ArrayList ruleHandlesList;
             LeapsRule leapsRule;
             LeapsRuleHandle ruleHandle;
-            for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
-                leapsRule = (LeapsRule) it.next();
+            for (final Iterator it = rules.iterator( ); it.hasNext( );) {
+                leapsRule = (LeapsRule) it.next( );
                 // some times rules do not have "normal" constraints and only
                 // not and exists
-                if ( leapsRule.getNumberOfColumns() > 0 ) {
+                if (leapsRule.getNumberOfColumns( ) > 0) {
                     ruleHandlesList = (ArrayList) this.leapsRulesToHandlesMap.remove( leapsRule );
-                    for ( int i = 0; i < ruleHandlesList.size(); i++ ) {
+                    for (int i = 0; i < ruleHandlesList.size( ); i++) {
                         ruleHandle = (LeapsRuleHandle) ruleHandlesList.get( i );
                         // 
-                        this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) ).removeRule( this,
-                                                                                                           ruleHandle );
+                        this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) )
+                            .removeRule( this, ruleHandle );
                     }
                 }
                 //
             }
-            final Rule rule = ((LeapsRule) rules.get( 0 )).getRule();
+            final Rule rule = ( (LeapsRule) rules.get( 0 ) ).getRule( );
             final FastMap activations = (FastMap) this.rulesActivationsMap.remove( rule );
-            if ( activations != null ) {
-                for ( final Iterator activationsIt = activations.keySet().iterator(); activationsIt.hasNext(); ) {
-                    final Activation activation = (Activation) activationsIt.next();
-                    ((LeapsTuple) activation.getTuple()).setActivation( null );
+            if (activations != null) {
+                for (final Iterator activationsIt = activations.keySet( ).iterator( ); activationsIt.hasNext( );) {
+                    final Activation activation = (Activation) activationsIt.next( );
+                    ( (LeapsTuple) activation.getTuple( ) ).setActivation( null );
                     this.tms.removeLogicalDependencies( activation,
-                                                        activation.getPropagationContext(),
+                                                        activation.getPropagationContext( ),
                                                         rule );
                 }
             }
 
-            propagateQueuedActions();
-        } finally {
-            this.getLock().unlock();
+            propagateQueuedActions( );
         }
+        finally {
+            this.getLock( ).unlock( );
+        }
     }
 
     /**
      * main loop
      * 
      */
-    public final synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
+    public final synchronized void fireAllRules( final AgendaFilter agendaFilter )
+            throws FactException {
         // If we're already firing a rule, then it'll pick up
         // the firing for any other assertObject(..) that get
         // nested inside, avoiding concurrent-modification
         // exceptions, depending on code paths of the actions.
 
-        if ( !this.firing ) {
+        if (!this.firing) {
             try {
                 this.firing = true;
                 boolean nothingToProcess = false;
-                while ( !nothingToProcess ) {
+                while (!nothingToProcess) {
+                    // check for the initial fact
+                    for (Iterator rulesIt = this.noPositiveColumnsRules.iterator( ); rulesIt.hasNext( );) {
+                        LeapsRule rule = ( (LeapsRuleHandle) rulesIt.next( ) ).getLeapsRule( );
+                        final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter( ),
+                                                                                           PropagationContext.ASSERTION,
+                                                                                           null,
+                                                                                           null );
+                        TokenEvaluator.processAfterAllPositiveConstraintOk( new LeapsTuple( new LeapsFactHandle[0],
+                                                                                            rule,
+                                                                                            context ),
+                                                                            rule,
+                                                                            this );
+
+                    }
+                    this.noPositiveColumnsRules.clear( );
                     // normal rules with required columns
-                    while ( !this.mainStack.empty() ) {
-                        final Token token = this.peekTokenOnTop();
+                    while (!this.mainStack.empty( )) {
+                        final Token token = this.peekTokenOnTop( );
                         boolean done = false;
-                        while ( !done ) {
-                            if ( !token.isResume() ) {
-                                if ( token.hasNextRuleHandle() ) {
-                                    token.nextRuleHandle();
-                                } else {
+                        while (!done) {
+                            if (!token.isResume( )) {
+                                if (token.hasNextRuleHandle( )) {
+                                    token.nextRuleHandle( );
+                                }
+                                else {
                                     // we do not pop because something might get
                                     // asserted
                                     // and placed on hte top of the stack during
                                     // firing
-                                    this.removeTokenFromStack( (LeapsFactHandle) token.getDominantFactHandle() );
+                                    this.removeTokenFromStack( (LeapsFactHandle) token.getDominantFactHandle( ) );
                                     done = true;
                                 }
                             }
-                            if ( !done ) {
+                            if (!done) {
                                 try {
-                                    // ok. now we have tuple, dominant fact and
-                                    // rules and ready to seek to checks if any
+                                    // ok. now we have tuple, dominant fact
+                                    // and
+                                    // rules and ready to seek to checks if
+                                    // any
                                     // agendaItem
                                     // matches on current rule
                                     TokenEvaluator.evaluate( token );
                                     // something was found so set marks for
                                     // resume processing
-                                    if ( token.getDominantFactHandle() != null ) {
-                                        token.setResume( true );
+                                    if (token.getDominantFactHandle( ) != null) {
+                                        if (token.getDominantFactHandle( )
+                                                 .getObject( )
+                                                 .getClass( ) != FromConstraintFactDriver.class) {
+                                            token.setResume( true );
+                                        }
                                         done = true;
                                     }
-                                } catch ( final NoMatchesFoundException ex ) {
+                                }
+                                catch (final NoMatchesFoundException ex) {
                                     token.setResume( false );
                                 }
                             }
                             // we put everything on agenda
                             // and if there is no modules or anything like it
                             // it would fire just activated rule
-                            while ( this.agenda.fireNextItem( agendaFilter ) ) {
+                            while (this.agenda.fireNextItem( agendaFilter )) {
                                 ;
                             }
                         }
@@ -634,20 +700,23 @@
                     // pick activations generated by retraction or assert
                     // can generate activations off exists and not pending
                     // tuples
-                    while ( this.agenda.fireNextItem( agendaFilter ) ) {
+                    while (this.agenda.fireNextItem( agendaFilter )) {
                         ;
                     }
-                    if ( this.mainStack.empty() ) {
+                    if (this.mainStack.empty( )) {
                         nothingToProcess = true;
                     }
                 }
                 // mark when method was called last time
-                this.idLastFireAllAt = ((LeapsFactHandleFactory) this.handleFactory).getNextId();
+                this.idLastFireAllAt = ( (LeapsFactHandleFactory) this.handleFactory ).getNextId( );
                 // set all factTables to be reseeded
-                for ( final Iterator it = this.factTables.values().iterator(); it.hasNext(); ) {
-                    ((FactTable) it.next()).setReseededStack( true );
+                for (final Iterator it = this.factTables.values( ).iterator( ); it.hasNext( );) {
+                    ( (FactTable) it.next( ) ).setReseededStack( true );
                 }
-            } finally {
+                // clear table that is used to trigger From constraints
+                this.getFactTable( FromConstraintFactDriver.class ).clear( );
+            }
+            finally {
                 this.firing = false;
             }
         }
@@ -662,14 +731,14 @@
         Object key;
         ret = ret + "\n" + "Working memory";
         ret = ret + "\n" + "Fact Tables by types:";
-        for ( final Iterator it = this.factTables.keySet().iterator(); it.hasNext(); ) {
-            key = it.next();
+        for (final Iterator it = this.factTables.keySet( ).iterator( ); it.hasNext( );) {
+            key = it.next( );
             ret = ret + "\n" + "******************   " + key;
-            ret = ret + ((FactTable) this.factTables.get( key )).toString();
+            ret = ret + ( (FactTable) this.factTables.get( key ) ).toString( );
         }
         ret = ret + "\n" + "Stack:";
-        for ( final Iterator it = this.mainStack.iterator(); it.hasNext(); ) {
-            ret = ret + "\n" + "\t" + it.next();
+        for (final Iterator it = this.mainStack.iterator( ); it.hasNext( );) {
+            ret = ret + "\n" + "\t" + it.next( );
         }
         return ret;
     }
@@ -684,20 +753,20 @@
      * @throws AssertionException
      *             If an error occurs while asserting.
      */
-    public final void assertTuple(final LeapsTuple tuple) {
-        final PropagationContext context = tuple.getContext();
-        final Rule rule = tuple.getLeapsRule().getRule();
+    public final void assertTuple( final LeapsTuple tuple ) {
+        final PropagationContext context = tuple.getContext( );
+        final Rule rule = tuple.getLeapsRule( ).getRule( );
         // if the current Rule is no-loop and the origin rule is the same then
         // return
-        if ( rule.getNoLoop() && rule.equals( context.getRuleOrigin() ) ) {
+        if (rule.getNoLoop( ) && rule.equals( context.getRuleOrigin( ) )) {
             return;
         }
         //
-        final Duration dur = rule.getDuration();
+        final Duration dur = rule.getDuration( );
 
         Activation agendaItem;
-        if ( dur != null && dur.getDuration( tuple ) > 0 ) {
-            agendaItem = new ScheduledAgendaItem( context.getPropagationNumber(),
+        if (dur != null && dur.getDuration( tuple ) > 0) {
+            agendaItem = new ScheduledAgendaItem( context.getPropagationNumber( ),
                                                   tuple,
                                                   this.agenda,
                                                   context,
@@ -705,25 +774,28 @@
             this.agenda.scheduleItem( (ScheduledAgendaItem) agendaItem );
             tuple.setActivation( agendaItem );
             agendaItem.setActivated( true );
-            this.getAgendaEventSupport().fireActivationCreated( agendaItem );
-        } else {
-            final LeapsRule leapsRule = tuple.getLeapsRule();
-            AgendaGroupImpl agendaGroup = leapsRule.getAgendaGroup();
-            if ( agendaGroup == null ) {
-                if ( rule.getAgendaGroup() == null || rule.getAgendaGroup().equals( "" ) || rule.getAgendaGroup().equals( AgendaGroup.MAIN ) ) {
+            this.getAgendaEventSupport( ).fireActivationCreated( agendaItem );
+        }
+        else {
+            final LeapsRule leapsRule = tuple.getLeapsRule( );
+            AgendaGroupImpl agendaGroup = leapsRule.getAgendaGroup( );
+            if (agendaGroup == null) {
+                if (rule.getAgendaGroup( ) == null || rule.getAgendaGroup( ).equals( "" )
+                        || rule.getAgendaGroup( ).equals( AgendaGroup.MAIN )) {
                     // Is the Rule AgendaGroup undefined? If it is use MAIN,
                     // which is added to the Agenda by default
                     agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( AgendaGroup.MAIN );
-                } else {
+                }
+                else {
                     // AgendaGroup is defined, so try and get the AgendaGroup
                     // from the Agenda
-                    agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup() );
+                    agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup( ) );
                 }
 
-                if ( agendaGroup == null ) {
+                if (agendaGroup == null) {
                     // The AgendaGroup is defined but not yet added to the
                     // Agenda, so create the AgendaGroup and add to the Agenda.
-                    agendaGroup = new AgendaGroupImpl( rule.getAgendaGroup() );
+                    agendaGroup = new AgendaGroupImpl( rule.getAgendaGroup( ) );
                     this.agenda.addAgendaGroup( agendaGroup );
                 }
 
@@ -731,11 +803,11 @@
             }
 
             // set the focus if rule autoFocus is true
-            if ( rule.getAutoFocus() ) {
+            if (rule.getAutoFocus( )) {
                 this.agenda.setFocus( agendaGroup );
             }
 
-            agendaItem = new AgendaItem( context.getPropagationNumber(),
+            agendaItem = new AgendaItem( context.getPropagationNumber( ),
                                          tuple,
                                          context,
                                          rule );
@@ -744,30 +816,28 @@
 
             tuple.setActivation( agendaItem );
             agendaItem.setActivated( true );
-            this.getAgendaEventSupport().fireActivationCreated( agendaItem );
+            this.getAgendaEventSupport( ).fireActivationCreated( agendaItem );
         }
 
         // retract support
-        final LeapsFactHandle[] factHandles = (LeapsFactHandle[]) tuple.getFactHandles();
-        for ( int i = 0; i < factHandles.length; i++ ) {
+        final LeapsFactHandle[] factHandles = (LeapsFactHandle[]) tuple.getFactHandles( );
+        for (int i = 0; i < factHandles.length; i++) {
             factHandles[i].addActivatedTuple( tuple );
         }
 
         // rules remove support
         FastMap activations = (FastMap) this.rulesActivationsMap.get( rule );
-        if ( activations == null ) {
-            activations = new FastMap();
-            this.rulesActivationsMap.put( rule,
-                                          activations );
+        if (activations == null) {
+            activations = new FastMap( );
+            this.rulesActivationsMap.put( rule, activations );
         }
-        activations.put( agendaItem,
-                         agendaItem );
+        activations.put( agendaItem, agendaItem );
     }
 
     List getActivations() {
-        List ret = new ArrayList();
-        for ( final Iterator it = this.rulesActivationsMap.values().iterator(); it.hasNext(); ) {
-            ret.addAll( ((FastMap) it.next()).values() );
+        List ret = new ArrayList( );
+        for (final Iterator it = this.rulesActivationsMap.values( ).iterator( ); it.hasNext( );) {
+            ret.addAll( ( (FastMap) it.next( ) ).values( ) );
         }
 
         return ret;
@@ -777,42 +847,38 @@
         return ++this.propagationIdCounter;
     }
 
-    public QueryResults getQueryResults(final String queryName) {
+    public QueryResults getQueryResults( final String queryName ) {
         final IdentityMap map = (IdentityMap) this.queryResults.get( queryName );
-        if ( map == null ) {
+        if (map == null) {
             return null;
         }
 
-        final LinkedList list = new LinkedList();
-        for ( final Iterator it = map.keySet().iterator(); it.hasNext(); ) {
-            list.add( it.next() );
+        final LinkedList list = new LinkedList( );
+        for (final Iterator it = map.keySet( ).iterator( ); it.hasNext( );) {
+            list.add( it.next( ) );
         }
-        if ( !list.isEmpty() ) {
-            final Query queryRule = (Query) ((LeapsTuple) list.get( 0 )).getLeapsRule().getRule();
-            return new LeapsQueryResults( list,
-                                          queryRule,
-                                          this );
-        } else {
+        if (!list.isEmpty( )) {
+            final Query queryRule = (Query) ( (LeapsTuple) list.get( 0 ) ).getLeapsRule( )
+                                                                          .getRule( );
+            return new LeapsQueryResults( list, queryRule, this );
+        }
+        else {
             return null;
         }
     }
 
-    void addToQueryResults(final String query,
-                           final Tuple tuple) {
+    void addToQueryResults( final String query, final Tuple tuple ) {
         IdentityMap map = (IdentityMap) this.queryResults.get( query );
-        if ( map == null ) {
-            map = new IdentityMap();
-            this.queryResults.put( query,
-                                   map );
+        if (map == null) {
+            map = new IdentityMap( );
+            this.queryResults.put( query, map );
         }
-        map.put( tuple,
-                 tuple );
+        map.put( tuple, tuple );
     }
 
-    void removeFromQueryResults(final String query,
-                                final Tuple tuple) {
+    void removeFromQueryResults( final String query, final Tuple tuple ) {
         final IdentityMap map = (IdentityMap) this.queryResults.get( query );
-        if ( map != null ) {
+        if (map != null) {
             map.remove( tuple );
         }
     }
@@ -820,34 +886,31 @@
     /**
      * to store facts to cursor over it
      */
-    private final Map factTables = new FactTables();
+    private final Map factTables = new FactTables( );
 
-    class FactTables
-        implements
-        Map,
-        Serializable {
-        private LinkedList tables = new LinkedList();
+    class FactTables implements Map, Serializable {
+        private LinkedList tables = new LinkedList( );
 
-        private HashMap    map    = new HashMap();
+        private HashMap    map    = new HashMap( );
 
         public int size() {
-            return this.tables.size();
+            return this.tables.size( );
         }
 
         public void clear() {
-            this.tables.clear();
-            this.map.clear();
+            this.tables.clear( );
+            this.map.clear( );
         }
 
         public boolean isEmpty() {
-            return this.tables.isEmpty();
+            return this.tables.isEmpty( );
         }
 
-        public boolean containsKey(Object key) {
+        public boolean containsKey( Object key ) {
             return this.map.containsKey( key );
         }
 
-        public boolean containsValue(Object value) {
+        public boolean containsValue( Object value ) {
             return this.map.containsValue( value );
         }
 
@@ -855,36 +918,37 @@
             return this.tables;
         }
 
-        public void putAll(Map t) {
-            this.tables.addAll( t.values() );
+        public void putAll( Map t ) {
+            this.tables.addAll( t.values( ) );
             this.map.putAll( t );
         }
 
         public Set entrySet() {
-            return this.map.entrySet();
+            return this.map.entrySet( );
         }
 
         public Set keySet() {
-            return this.map.keySet();
+            return this.map.keySet( );
         }
 
-        public Object get(Object key) {
+        public Object get( Object key ) {
             return this.map.get( key );
 
         }
 
-        public Object remove(Object key) {
+        public Object remove( Object key ) {
             Object ret = this.map.remove( key );
             this.tables.remove( ret );
             return ret;
         }
 
-        public Object put(Object key,
-                          Object value) {
+        public Object put( Object key, Object value ) {
             this.tables.add( value );
-            this.map.put( key,
-                          value );
+            this.map.put( key, value );
             return value;
         }
     }
+
+    private class FromConstraintFactDriver implements Serializable {
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/Token.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -70,8 +70,7 @@
     private Iterator rulesIterator() {
         if (this.rules == null) {
             if (this.dominantFactHandle != null) {
-                this.rules = this.workingMemory.getFactTable( this.dominantFactHandle.getObject( )
-                                                                                     .getClass( ) )
+                this.rules = this.workingMemory.getFactTable( LeapsBuilder.getLeapsClassType( this.dominantFactHandle.getObject( )  ) )
                                                .getRulesIterator( );
             }
         }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/TokenEvaluator.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -16,11 +16,15 @@
  * limitations under the License.
  */
 
+import java.util.Iterator;
+
+import org.drools.common.DefaultFactHandle;
 import org.drools.common.InternalFactHandle;
 import org.drools.leaps.util.Table;
 import org.drools.leaps.util.TableIterator;
 import org.drools.rule.EvalCondition;
 import org.drools.rule.InvalidRuleException;
+import org.drools.spi.Tuple;
 
 /**
  * helper class that does condition evaluation on token when working memory does
@@ -51,34 +55,41 @@
         final InternalFactHandle dominantFactHandle = token.getDominantFactHandle( );
         if (leapsRule.getColumnConstraintsAtPosition( dominantFactPosition )
                      .isAllowedAlpha( dominantFactHandle, token, workingMemory )) {
-            final Class dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
+            final Object dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
             final TableIterator[] iterators = new TableIterator[numberOfColumns];
             // getting iterators first
             for (int i = 0; i < numberOfColumns; i++) {
-                if (i == dominantFactPosition) {
-                    iterators[i] = Table.singleItemIterator( dominantFactHandle );
-                }
-                else {
-                    final Class columnClass = leapsRule.getColumnClassObjectTypeAtPosition( i );
-                    final ColumnConstraints constraints = leapsRule.getColumnConstraintsAtPosition( i );
-                    final FactTable factTable = workingMemory.getFactTable( columnClass );
-                    final LeapsFactHandle startFactHandle = ( dominantClass == columnClass ) ? new LeapsFactHandle( dominantFactHandle.getRecency( ) - 1,
-                                                                                                                    new Object( ) )
-                            : (LeapsFactHandle) dominantFactHandle;
-                    //
-                    if (i > 0 && constraints.isAlphaPresent( )) {
-                        iterators[i] = factTable.constrainedIteratorFromPositionToTableStart( workingMemory,
-                                                                                              constraints,
-                                                                                              startFactHandle,
-                                                                                              ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
-                                                                                                      : startFactHandle ) );
+                final Object columnClass = leapsRule.getColumnClassObjectTypeAtPosition( i );
+                final ColumnConstraints constraints = leapsRule.getColumnConstraintsAtPosition( i );
+                // we do not need iterators for From constraint
+                if (constraints.getClass( ) != FromConstraint.class) {
+                    if (i == dominantFactPosition) {
+                        iterators[i] = Table.singleItemIterator( dominantFactHandle );
                     }
                     else {
-                        iterators[i] = factTable.iteratorFromPositionToTableStart( startFactHandle,
-                                                                                   ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
-                                                                                           : startFactHandle ) );
+                        final FactTable factTable = workingMemory.getFactTable( columnClass );
+                        final LeapsFactHandle startFactHandle = ( dominantClass == columnClass ) ? new LeapsFactHandle( dominantFactHandle.getRecency( ) - 1,
+                                                                                                                        new Object( ) )
+                                : (LeapsFactHandle) dominantFactHandle;
+                        if (i > 0 && constraints.isAlphaPresent( )) {
+                            iterators[i] = factTable.constrainedIteratorFromPositionToTableStart( workingMemory,
+                                                                                                  constraints,
+                                                                                                  startFactHandle,
+                                                                                                  ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
+                                                                                                          : startFactHandle ) );
+                        }
+                        else {
+                            iterators[i] = factTable.iteratorFromPositionToTableStart( startFactHandle,
+                                                                                       ( token.isResume( ) ? (LeapsFactHandle) token.get( i )
+                                                                                               : startFactHandle ) );
+                        }
                     }
                 }
+                else {
+                    // we do not need iterator for from constraint
+                    // it has its own
+                    iterators[i] = null;
+                }
             }
 
             // check if any iterators are empty to abort
@@ -89,23 +100,28 @@
             TableIterator currentIterator;
             for (int i = 0; i < numberOfColumns; i++) {
                 currentIterator = iterators[i];
-                // check if one of them is empty and immediate return
-                if (currentIterator.isEmpty( )) {
-                    throw new NoMatchesFoundException( );
-                }
-                else {
-                    if (!doReset) {
-                        if (skip && currentIterator.hasNext( )
-                                && !currentIterator.peekNext( ).equals( token.get( i ) )) {
-                            // we tried to resume but our fact handle at marker
-                            // disappear no need to resume just reset all interators
-                            // positioned at the marker where we stoped last time
-                            skip = false;
-                            doReset = true;
-                        }
+                if (currentIterator != null) {
+                    // check if one of them is empty and immediate return
+                    if (currentIterator.isEmpty( )) {
+                        throw new NoMatchesFoundException( );
                     }
                     else {
-                        currentIterator.reset( );
+                        if (!doReset) {
+                            if (skip && currentIterator.hasNext( )
+                                    && !currentIterator.peekNext( ).equals( token.get( i ) )) {
+                                // we tried to resume but our fact handle at
+                                // marker
+                                // disappear no need to resume just reset all
+                                // interators
+                                // positioned at the marker where we stoped last
+                                // time
+                                skip = false;
+                                doReset = true;
+                            }
+                        }
+                        else {
+                            currentIterator.reset( );
+                        }
                     }
                 }
             }
@@ -117,7 +133,8 @@
             final int stopIteratingCount = numberOfColumns - 1;
             while (!done) {
                 currentIterator = iterators[jj];
-                if (!currentIterator.hasNext( )) {
+                // if it's not From and does not have next
+                if (currentIterator != null && !currentIterator.hasNext( )) {
                     if (jj == 0) {
                         done = true;
                     }
@@ -132,23 +149,38 @@
                     }
                 }
                 else {
-                    final LeapsFactHandle currentFactHandle = (LeapsFactHandle) currentIterator.next( );
-                    // check if match found we need to check only beta for
-                    // dominant fact
-                    // alpha was already checked
                     boolean localMatch = false;
-                    if (!skip) {
-                        if (jj != 0 || jj == dominantFactPosition) {
-                            localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
-                                                  .isAllowedBeta( currentFactHandle,
+                    LeapsFactHandle currentFactHandle = null;
+                    if (currentIterator != null) {
+                        currentFactHandle = (LeapsFactHandle) currentIterator.next( );
+                        // check if match found we need to check only beta for
+                        // dominant fact
+                        // alpha was already checked
+                        if (!skip) {
+                            if (jj != 0 || jj == dominantFactPosition) {
+                                localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
+                                                      .isAllowedBeta( currentFactHandle,
+                                                                      token,
+                                                                      workingMemory );
+                            }
+                            else {
+                                localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
+                                                      .isAllowed( currentFactHandle,
                                                                   token,
                                                                   workingMemory );
+                            }
                         }
-                        else {
-                            localMatch = leapsRule.getColumnConstraintsAtPosition( jj )
-                                                  .isAllowed( currentFactHandle,
-                                                              token,
-                                                              workingMemory );
+                    }
+                    else {
+                        Object fromMatch = TokenEvaluator.evaluateFrom( (FromConstraint) leapsRule.getColumnConstraintsAtPosition( jj ),
+                                                                        token,
+                                                                        leapsRule,
+                                                                        workingMemory );
+                        if (fromMatch != null) {
+                            localMatch = true;
+                            // this is not a real fact. just to make it work with 
+                            // token / tuple
+                            currentFactHandle = new LeapsFactHandle( -1, fromMatch );
                         }
                     }
                     if (localMatch || skip) {
@@ -192,7 +224,7 @@
                                                               final LeapsRule leapsRule,
                                                               final LeapsWorkingMemory workingMemory ) {
         if (leapsRule.containsEvalConditions( )
-                && !TokenEvaluator.evaluateEvalConditions( leapsRule, tuple, workingMemory )) {
+                && !TokenEvaluator.evaluateEvalConditions( tuple, leapsRule, workingMemory )) {
             return false;
         }
         if (leapsRule.containsExistsColumns( )) {
@@ -201,13 +233,6 @@
         if (leapsRule.containsNotColumns( )) {
             TokenEvaluator.evaluateNotConditions( tuple, leapsRule, workingMemory );
         }
-        // put tuple onto fact tables that might affect activation status
-        // via exists or not conditions
-        final Class[] classes = leapsRule.getExistsNotColumnsClasses( );
-        for (int i = 0, length = classes.length; i < length; i++) {
-            workingMemory.getFactTable( classes[i] ).addTuple( tuple );
-        }
-
         // 
         if (tuple.isReadyForActivation( )) {
             // let agenda to do its work
@@ -215,6 +240,13 @@
             return true;
         }
         else {
+            // put tuple onto fact tables that might affect activation status
+            // via exists or not conditions
+            final Class[] classes = leapsRule.getExistsNotColumnsClasses( );
+            for (int i = 0, length = classes.length; i < length; i++) {
+                workingMemory.getFactTable( classes[i] ).addTuple( tuple );
+            }
+
             return false;
         }
     }
@@ -228,8 +260,30 @@
      * @return
      * @throws Exception
      */
-    private final static boolean evaluateEvalConditions( final LeapsRule leapsRule,
-                                                         final LeapsTuple tuple,
+    private final static Object evaluateFrom( final FromConstraint from,
+                                              final Tuple tuple,
+                                              final LeapsRule leapsRule,
+                                              final LeapsWorkingMemory workingMemory ) {
+        for (Iterator it = from.getProvider( ).getResults( tuple, workingMemory, null ); it.hasNext( );) {
+            Object object = it.next( );
+            if (from.isAllowed( new DefaultFactHandle( -1, object ), tuple, workingMemory )) {
+                return object;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * checks is EvalConditions isAllowed()
+     * 
+     * @param leapsRule
+     * @param tuple
+     * @param workingMemory
+     * @return
+     * @throws Exception
+     */
+    private final static boolean evaluateEvalConditions( final LeapsTuple tuple,
+                                                         final LeapsRule leapsRule,
                                                          final LeapsWorkingMemory workingMemory ) {
         final EvalCondition[] evals = leapsRule.getEvalConditions( );
         for (int i = 0; i < evals.length; i++) {
@@ -257,10 +311,12 @@
             final ColumnConstraints constraint = not[i];
             // scan table starting at start fact handle
             final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                                             .reverseOrderIterator( );
+                                                             .reverseOrderIterator( tuple, constraint );
+//            .reverseOrderIterator( );
             // stops if exists
             boolean done = false;
-            while (!done && tableIterator.hasNext( )) {
+            while (!done  && tableIterator.hasNext( )) {
+//                while (!done && tableIterator.hasNext( )) {
                 final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next( );
                 // check constraint conditions
                 if (constraint.isAllowed( factHandle, tuple, workingMemory )) {
@@ -290,7 +346,9 @@
         // scan table starting at start fact handle
         final ColumnConstraints constraint = rule.getNotColumnConstraints( )[index];
         final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                                         .iteratorFromPositionToTableEnd( startFactHandle );
+                                         .iteratorFromPositionToTableEnd( tuple, constraint, startFactHandle);
+//        .iteratorFromPositionToTableEnd( startFactHandle );
+//            .reverseOrderIterator( );
         // stops if exists
         boolean done = false;
         while (!done && tableIterator.hasNext( )) {
@@ -319,7 +377,8 @@
             final ColumnConstraints constraint = exists[i];
             // scan table starting at start fact handle
             final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType( ) )
-                                                             .reverseOrderIterator( );
+                                                             .reverseOrderIterator( tuple, constraint );
+//            .reverseOrderIterator( );
             // stop if exists
             boolean done = false;
             while (!done && tableIterator.hasNext( )) {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -50,7 +50,7 @@
         this.nextRecord = this.firstRecord;
     }
 
-    protected IteratorFromPositionToTableStart(final TableRecord startRecord,
+    public IteratorFromPositionToTableStart(final TableRecord startRecord,
             final TableRecord currentRecord) {
         this.firstRecord = startRecord;
         this.nextRecord = currentRecord;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/leaps/util/Table.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -53,8 +53,8 @@
         this.set = new TreeSet( new RecordComparator(comparator) );
     }
 
-    protected void clear() {
-        this.headRecord = new TableRecord( null );
+    public void clear() {
+        this.headRecord = null;
         this.empty = true;
         this.count = 0;
         this.set.clear( );
@@ -343,4 +343,8 @@
     public static TableIterator singleItemIterator( final Object object ) {
         return new IteratorFromPositionToTableStart( new TableRecord( object ) );
     }
+
+    public static TableIterator emptyIterator() {
+        return new IteratorFromPositionToTableStart( null, null );
+    }
 }

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/HashedTableComponentTest.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -0,0 +1,383 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.drools.DroolsTestCase;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.DefaultFactHandle;
+import org.drools.examples.manners.Chosen;
+import org.drools.examples.manners.Context;
+import org.drools.examples.manners.Count;
+import org.drools.examples.manners.Guest;
+import org.drools.examples.manners.LastSeat;
+import org.drools.examples.manners.Path;
+import org.drools.examples.manners.Seating;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.InvalidRuleException;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Not;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldConstraint;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.MockField;
+import org.drools.spi.Tuple;
+
+/**
+ * 
+ * @author Alexander Bagerman
+ *
+ */
+public class HashedTableComponentTest extends DroolsTestCase {
+
+    protected Package       pkg;
+
+
+    private ClassObjectType pathType;
+
+
+    private Evaluator       objectEqualEvaluator;
+
+    private Evaluator       integerEqualEvaluator;
+
+    private Path            p1Alex;
+
+    private Path            p2John;
+
+    private Path            p3Mike;
+
+    private Path            p4Alex;
+
+    private Path            p5Alex;
+
+    protected void setUp() throws Exception {
+
+        this.p1Alex = new Path( 1, 1, "Alex" );
+        this.p2John = new Path( 2, 1, "John" );
+        this.p3Mike = new Path( 3, 1, "Mike" );
+        this.p4Alex = new Path( 4, 1, "Alex" );
+        this.p5Alex = new Path( 1, 4, "Alex" );
+        this.pathType = new ClassObjectType( Path.class );
+
+        this.integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+        this.objectEqualEvaluator = ValueType.OBJECT_TYPE.getEvaluator( Operator.EQUAL );
+
+        this.pkg = new Package( "Miss Manners for Hashed Table Component" );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+     * WorkingMemoryImpl)'
+     */
+    public void testHashedTableComponentNoAlpha() throws Exception {
+
+        Rule r = this.getMakePathNoAlpha( );
+        this.pkg.addRule( r );
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        ruleBase.addPackage( this.pkg );
+        final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory( );
+        wm.assertObject( this.p1Alex );
+        wm.assertObject( this.p2John );
+        wm.assertObject( this.p3Mike );
+        wm.assertObject( this.p4Alex );
+        wm.assertObject( this.p5Alex );
+
+        Iterator it;
+        Tuple tuple;
+        FactTable ft = wm.getFactTable( Path.class );
+        ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints( )
+                                                                .next( );
+        LeapsFactHandle[] fh = new LeapsFactHandle[1];
+        fh[0] = new LeapsFactHandle( 99, p1Alex );
+        tuple = new LeapsTuple( fh, null, null );
+
+        it = ft.reverseOrderIterator( tuple, notConstraint );
+        assertSame( "Expected matching",
+                    ( (LeapsFactHandle) it.next( ) ).getObject( ),
+                    p1Alex );
+        assertSame( "Expected matching",
+                    ( (LeapsFactHandle) it.next( ) ).getObject( ),
+                    p5Alex );
+        assertFalse( "Did not expect any more data", it.hasNext( ) );
+
+        fh[0] = new LeapsFactHandle( 99, p3Mike );
+        tuple = new LeapsTuple( fh, null, null );
+
+        it = ft.reverseOrderIterator( tuple, notConstraint );
+        assertSame( "Expected matching",
+                    ( (LeapsFactHandle) it.next( ) ).getObject( ),
+                    p3Mike );
+        assertFalse( "Did not expect any more data", it.hasNext( ) );
+    }
+
+    /*
+     * Test method for
+     * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+     * WorkingMemoryImpl)'
+     */
+    public void testHashedTableComponentAlpha() throws Exception {
+
+        Rule r = this.getMakePathAlpha( );
+        this.pkg.addRule( r );
+        final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+        ruleBase.addPackage( this.pkg );
+        final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory( );
+
+        wm.assertObject( this.p1Alex );
+        wm.assertObject( this.p2John );
+        wm.assertObject( this.p3Mike );
+        wm.assertObject( this.p4Alex );
+        wm.assertObject( this.p5Alex );
+
+        Iterator it;
+        Tuple tuple;
+        FactTable ft = wm.getFactTable( Path.class );
+        ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints( )
+                                                                .next( );
+        LeapsFactHandle[] fh = new LeapsFactHandle[1];
+        fh[0] = new LeapsFactHandle( 99, p1Alex );
+        tuple = new LeapsTuple( fh, null, null );
+
+        it = ft.reverseOrderIterator( tuple, notConstraint );
+        assertFalse( "Did not expect any more data", it.hasNext( ) );
+
+        fh[0] = new LeapsFactHandle( 99, p3Mike );
+        tuple = new LeapsTuple( fh, null, null );
+
+        it = ft.reverseOrderIterator( tuple, notConstraint );
+        assertSame( "Expected matching",
+                    ( (LeapsFactHandle) it.next( ) ).getObject( ),
+                    p3Mike );
+        assertFalse( "Did not expect any more data", it.hasNext( ) );
+    }
+
+    /**
+     * <pre>
+     *     rule makePath() {
+     *         int pathId;
+     *         String pathGuestName;
+     *    
+     *         when {
+     *             Path( pathId:id, pathGuestName:guest )
+     *             (not Path( id == pathId, guestName == pathGuestName )
+     *         } then {
+     *             nothing;
+     *    
+     *         }
+     *     } 
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getMakePathAlpha() throws IntrospectionException, InvalidRuleException {
+        final Rule rule = new Rule( "makePathNoAlpha" );
+        // -----------
+        // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+        // -----------
+        final Column pathColumn = new Column( 0, this.pathType );
+        setFieldDeclaration( pathColumn, "id", "pathId" );
+
+        setFieldDeclaration( pathColumn, "guestName", "pathGuestName" );
+
+        rule.addPattern( pathColumn );
+
+        final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+        final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+        // -------------
+        // (not Path( id == seatingId, guestName == pathGuestName )
+        // -------------
+        final Column notPathColumn = new Column( 3, this.pathType );
+
+        notPathColumn.addConstraint( getLiteralConstraint( notPathColumn,
+                                                           "guestName",
+                                                           "Mike",
+                                                           this.objectEqualEvaluator ) );
+
+        notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+                                                                 "id",
+                                                                 pathIdDeclaration,
+                                                                 this.integerEqualEvaluator ) );
+        notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+                                                                 "guestName",
+                                                                 pathGuestNameDeclaration,
+                                                                 this.objectEqualEvaluator ) );
+
+        final Not not = new Not( );
+
+        not.addChild( notPathColumn );
+
+        rule.addPattern( not );
+
+        // ------------
+        // drools.assert( new Path( id, pathName, pathSeat ) );
+        // ------------
+        final Consequence consequence = new Consequence( ) {
+
+            public void evaluate( KnowledgeHelper drools, WorkingMemory workingMemory )
+                    throws ConsequenceException {
+                // empty
+            }
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    /**
+     * <pre>
+     *     rule makePath() {
+     *         int pathId;
+     *         String pathGuestName;
+     *    
+     *         when {
+     *             Path( pathId:id, pathGuestName:guest )
+     *             (not Path( id == pathId, guestName == pathGuestName )
+     *         } then {
+     *             nothing;
+     *    
+     *         }
+     *     } 
+     * </pre>
+     * 
+     * @return
+     * @throws IntrospectionException
+     * @throws InvalidRuleException
+     */
+    private Rule getMakePathNoAlpha() throws IntrospectionException, InvalidRuleException {
+        final Rule rule = new Rule( "makePathNoAlpha" );
+        // -----------
+        // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+        // -----------
+        final Column pathColumn = new Column( 0, this.pathType );
+        setFieldDeclaration( pathColumn, "id", "pathId" );
+
+        setFieldDeclaration( pathColumn, "guestName", "pathGuestName" );
+
+        rule.addPattern( pathColumn );
+
+        final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+        final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+        // -------------
+        // (not Path( id == seatingId, guestName == pathGuestName )
+        // -------------
+        final Column notPathColumn = new Column( 3, this.pathType );
+
+        notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+                                                                 "id",
+                                                                 pathIdDeclaration,
+                                                                 this.integerEqualEvaluator ) );
+        notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+                                                                 "guestName",
+                                                                 pathGuestNameDeclaration,
+                                                                 this.objectEqualEvaluator ) );
+
+        final Not not = new Not( );
+
+        not.addChild( notPathColumn );
+
+        rule.addPattern( not );
+
+        // ------------
+        // drools.assert( new Path( id, pathName, pathSeat ) );
+        // ------------
+        final Consequence consequence = new Consequence( ) {
+
+            public void evaluate( KnowledgeHelper drools, WorkingMemory workingMemory )
+                    throws ConsequenceException {
+                // empty
+            }
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    public static int getIndex( final Class clazz, final String name )
+            throws IntrospectionException {
+        final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz )
+                                                             .getPropertyDescriptors( );
+        for (int i = 0; i < descriptors.length; i++) {
+            if (descriptors[i].getName( ).equals( name )) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private FieldConstraint getLiteralConstraint( final Column column,
+                                                  final String fieldName,
+                                                  final Object fieldValue,
+                                                  final Evaluator evaluator )
+            throws IntrospectionException {
+        final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+        final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+        final FieldValue field = new MockField( fieldValue );
+
+        return new LiteralConstraint( extractor, evaluator, field );
+    }
+
+    private void setFieldDeclaration( final Column column,
+                                      final String fieldName,
+                                      final String identifier )
+            throws IntrospectionException {
+        final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+        final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+        column.addDeclaration( identifier, extractor );
+    }
+
+    private FieldConstraint getBoundVariableConstraint( final Column column,
+                                                        final String fieldName,
+                                                        final Declaration declaration,
+                                                        final Evaluator evaluator )
+            throws IntrospectionException {
+        final Class clazz = ( (ClassObjectType) column.getObjectType( ) ).getClassType( );
+
+        final FieldExtractor extractor = new ClassFieldExtractor( clazz, fieldName );
+
+        return new VariableConstraint( extractor, declaration, evaluator );
+    }
+
+}

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/LogicalAssertionTest.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -71,7 +71,7 @@
                                                     new ArrayList(),
                                                     new ArrayList(),
                                                     new ArrayList(),
-                                                    new ArrayList() );
+                                                    new ArrayList()  );
 
         final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
         PropagationContext context1;
@@ -130,7 +130,7 @@
         final LeapsRule leapsRule1 = new LeapsRule( rule1,
                                                     new ArrayList(),
                                                     new ArrayList(),
-                                                    new ArrayList(),
+                                                    new ArrayList(), 
                                                     new ArrayList() );
 
         final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
@@ -225,7 +225,7 @@
         final LeapsRule leapsRule1 = new LeapsRule( rule1,
                                                     new ArrayList(),
                                                     new ArrayList(),
-                                                    new ArrayList(),
+                                                    new ArrayList(), 
                                                     new ArrayList() );
 
         final LeapsFactHandle tuple1FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
@@ -298,7 +298,7 @@
         final LeapsRule leapsRule1 = new LeapsRule( rule1,
                                                     new ArrayList(),
                                                     new ArrayList(),
-                                                    new ArrayList(),
+                                                    new ArrayList(), 
                                                     new ArrayList() );
 
         final LeapsFactHandle tuple1Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );

Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java	2006-08-19 05:24:46 UTC (rev 5944)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/leaps/SchedulerTest.java	2006-08-19 05:27:40 UTC (rev 5945)
@@ -78,7 +78,7 @@
         final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
         factHandlesTuple[0] = tupleFactHandle;
 
-        final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+        final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
         final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
                                                  (LeapsRule) leapsRules.get( 0 ),
                                                  context );
@@ -137,7 +137,7 @@
                     final LeapsFactHandle tupleFactHandleIn = (LeapsFactHandle) workingMemory.assertObject( "tuple object in" );
                     final LeapsFactHandle[] factHandlesTupleIn = new LeapsFactHandle[1];
                     factHandlesTupleIn[0] = tupleFactHandleIn;
-                    final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+                    final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
                     final LeapsTuple tupleIn = new LeapsTuple( factHandlesTupleIn,
                                                                (LeapsRule) leapsRules.get( 0 ),
                                                                context2 );
@@ -156,7 +156,7 @@
         final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
         factHandlesTuple[0] = tupleFactHandle;
 
-        final ArrayList leapsRules = (ArrayList) Builder.processRule( rule );
+        final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
         final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
                                                  (LeapsRule) leapsRules.get( 0 ),
                                                  context );




More information about the jboss-svn-commits mailing list