[jboss-svn-commits] JBL Code SVN: r6972 - in labs/jbossrules/trunk: . drools-leaps drools-leaps/src drools-leaps/src/main drools-leaps/src/main/java drools-leaps/src/main/java/org drools-leaps/src/main/java/org/drools drools-leaps/src/main/java/org/drools/leaps drools-leaps/src/main/java/org/drools/leaps/conflict drools-leaps/src/main/java/org/drools/leaps/util drools-leaps/src/test drools-leaps/src/test/java drools-leaps/src/test/java/org drools-leaps/src/test/java/org/drools drools-leaps/src/test/java/org/drools/leaps drools-leaps/src/test/java/org/drools/leaps/util
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Oct 20 13:34:16 EDT 2006
Author: mark.proctor at jboss.com
Date: 2006-10-20 13:34:03 -0400 (Fri, 20 Oct 2006)
New Revision: 6972
Added:
labs/jbossrules/trunk/drools-leaps/
labs/jbossrules/trunk/drools-leaps/src/
labs/jbossrules/trunk/drools-leaps/src/main/
labs/jbossrules/trunk/drools-leaps/src/main/java/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java
labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java
labs/jbossrules/trunk/drools-leaps/src/test/
labs/jbossrules/trunk/drools-leaps/src/test/java/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/conflict/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java
labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java
Log:
JBRULES-531 move LEAPS to its own module
-Leaps is now in its own module, but still need to hook it into the main build system.
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/AlphaMemory.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,35 @@
+package org.drools.leaps;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Tuple;
+
+class AlphaMemory {
+ private final IdentityMap alphaChecks = new IdentityMap();
+
+ AlphaMemory() {
+
+ }
+
+ boolean checkAlpha(final AlphaNodeFieldConstraint alpha,
+ final InternalFactHandle factHandle,
+ final Tuple tuple,
+ final WorkingMemory workingMemory) {
+ Boolean ret = (Boolean) this.alphaChecks.get( factHandle );
+ if ( ret == null ) {
+ ret = new Boolean( alpha.isAllowed( factHandle.getObject(),
+ tuple,
+ workingMemory ) );
+ this.alphaChecks.put( factHandle,
+ ret );
+ }
+
+ return ret.booleanValue();
+ }
+
+ boolean isAlphaBeenChecked(final InternalFactHandle factHandle) {
+ return this.alphaChecks != null && this.alphaChecks.containsKey( factHandle );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Builder.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,234 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.common.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.rule.And;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Exists;
+import org.drools.rule.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Not;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+
+/**
+ * A Rule<code>Builder</code> to process <code>Rule</code>s for use with
+ * Leaps WorkingMemories. Produces list of Leaps rules that wrap Rule and can be
+ * used in Leaps algorithm. All methods are static
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class Builder {
+ /**
+ * follows RETEOO logic flow but returns leaps rules list
+ *
+ * @param rule
+ * @return list of leaps rule
+ * @throws InvalidPatternException
+ */
+ final protected static List processRule(final Rule rule) throws InvalidPatternException {
+ final ArrayList leapsRules = new ArrayList();
+ final And[] and = rule.getTransformedLhs();
+ for ( int i = 0, length = and.length; i < length; i++ ) {
+ leapsRules.addAll( processRuleForAnd( and[i],
+ rule ) );
+ }
+ return leapsRules;
+ }
+
+ /**
+ * Creates list of leaps rules for each individual And
+ *
+ * @param and
+ * @param rule
+ * @return list of leaps rules for the given And
+ */
+ final private static List processRuleForAnd(final And and,
+ final Rule rule) {
+ ColumnConstraints constraints;
+ final ArrayList leapsRules = new ArrayList();
+ final ArrayList cols = new ArrayList();
+ final ArrayList notCols = new ArrayList();
+ final ArrayList existsCols = new ArrayList();
+ final ArrayList evalConditions = new ArrayList();
+ for ( final Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
+ final Object object = it.next();
+ if ( object instanceof EvalCondition ) {
+ final EvalCondition eval = (EvalCondition) object;
+ evalConditions.add( eval );
+ } else {
+ if ( object instanceof Column ) {
+ constraints = Builder.processColumn( (Column) object,
+ true );
+ // create column constraints
+ } else {
+ // NOTS and EXISTS
+ GroupElement ce = (GroupElement) object;
+ while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
+ ce = (GroupElement) ce.getChildren().get( 0 );
+ }
+ constraints = Builder.processColumn( (Column) ce.getChildren().get( 0 ),
+ false );
+ }
+ if ( object instanceof Not ) {
+ notCols.add( constraints );
+ } else if ( object instanceof Exists ) {
+ existsCols.add( constraints );
+ } else {
+ cols.add( constraints );
+ }
+ }
+ }
+
+ // check eval for presence of required declarations
+ checkEvalUnboundDeclarations( rule,
+ evalConditions );
+ //
+ leapsRules.add( new LeapsRule( rule,
+ cols,
+ notCols,
+ existsCols,
+ evalConditions ) );
+
+ return leapsRules;
+ }
+
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ static void checkEvalUnboundDeclarations(final Rule rule,
+ final ArrayList evals) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( final Iterator it = evals.iterator(); it.hasNext(); ) {
+ final EvalCondition ec = (EvalCondition) it.next();
+ final Declaration[] declarations = ec.getRequiredDeclarations();
+ for ( int i = 0, length = declarations.length; i < length; i++ ) {
+ if ( rule.getDeclaration( declarations[i].getIdentifier() ) == null ) {
+ list.add( declarations[i].getIdentifier() );
+ }
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+ }
+
+ /**
+ * extracts column specific constraints and packages it into
+ * <code>ColumnConstraints</code>
+ *
+ * @param column
+ * @param and
+ * @return leaps packaged ColumnConstraints
+ */
+ final private static ColumnConstraints processColumn(final Column column,
+ final boolean removeIdentities) {
+ BetaConstraints binder;
+ final List alphaConstraints = new ArrayList();
+ final List predicateConstraints = new ArrayList();
+
+ final List constraints = column.getConstraints();
+
+ final Map declarations = new HashMap();
+
+ if ( column.getDeclaration() != null ) {
+ final Declaration declaration = column.getDeclaration();
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier(),
+ declaration );
+ }
+
+ for ( final Iterator it = constraints.iterator(); it.hasNext(); ) {
+ final Object object = it.next();
+ // Check if its a declaration
+ if ( object instanceof Declaration ) {
+ final Declaration declaration = (Declaration) object;
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier(),
+ declaration );
+ continue;
+ }
+
+ final AlphaNodeFieldConstraint fieldConstraint = (AlphaNodeFieldConstraint) object;
+ if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+ alphaConstraints.add( fieldConstraint );
+ } else {
+ predicateConstraints.add( fieldConstraint );
+ }
+ }
+
+ if ( !predicateConstraints.isEmpty() ) {
+ binder = new DefaultBetaConstraints( (AlphaNodeFieldConstraint[]) predicateConstraints.toArray( new AlphaNodeFieldConstraint[predicateConstraints.size()] ) );
+ } else {
+ binder = new DefaultBetaConstraints();
+ }
+
+ return new ColumnConstraints( column,
+ alphaConstraints,
+ binder );
+ }
+
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ private static void checkUnboundDeclarations(final Map declarations,
+ final Declaration[] requiredDeclarations) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( int i = 0, length = requiredDeclarations.length; i < length; i++ ) {
+ if ( declarations.get( requiredDeclarations[i].getIdentifier() ) == null ) {
+ list.add( requiredDeclarations[i].getIdentifier() );
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ColumnConstraints.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,123 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.drools.WorkingMemory;
+import org.drools.common.BetaConstraints;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Column;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Tuple;
+
+/**
+ * Collection of <code>Column</code> specific constraints
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class ColumnConstraints
+ implements
+ Serializable {
+ private Object classType;
+
+ private final AlphaNodeFieldConstraint[] alphaConstraints;
+
+ private final boolean alphaPresent;
+
+ private final BetaConstraints beta;
+
+ private final boolean betaPresent;
+
+ public ColumnConstraints(final Column column,
+ final List alpha,
+ final BetaConstraints beta) {
+ this.classType = LeapsBuilder.getLeapsClassType( column.getObjectType() );
+
+ if ( beta != null ) {
+ this.beta = beta;
+ this.betaPresent = true;
+ } else {
+ this.beta = null;
+ this.betaPresent = false;
+ }
+ if ( alpha != null && alpha.size() > 0 ) {
+ this.alphaConstraints = (AlphaNodeFieldConstraint[]) alpha.toArray( new AlphaNodeFieldConstraint[0] );
+ this.alphaPresent = true;
+ } else {
+ this.alphaConstraints = null;
+ this.alphaPresent = false;
+ }
+ }
+
+ protected final Object getClassType() {
+ return this.classType;
+ }
+
+ protected final boolean isAllowed(final InternalFactHandle factHandle,
+ final Tuple tuple,
+ final WorkingMemory workingMemory) {
+ return this.isAllowedAlpha( factHandle,
+ tuple,
+ workingMemory ) && this.isAllowedBeta( factHandle,
+ tuple,
+ workingMemory );
+ }
+
+ public final boolean isAllowedAlpha(final InternalFactHandle factHandle,
+ final Tuple tuple,
+ final WorkingMemory workingMemory) {
+ if ( this.alphaPresent ) {
+ for ( int i = 0, length = this.alphaConstraints.length; i < length; i++ ) {
+ // escape immediately if some condition does not match
+ if ( !this.alphaConstraints[i].isAllowed( factHandle.getObject(),
+ tuple,
+ workingMemory ) ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ protected final boolean isAllowedBeta(final InternalFactHandle factHandle,
+ final Tuple tuple,
+ final WorkingMemory workingMemory) {
+ if ( this.betaPresent ) {
+ return this.beta.isAllowed( factHandle,
+ tuple,
+ workingMemory );
+ }
+
+ return true;
+ }
+
+ protected final boolean isAlphaPresent() {
+ return this.alphaPresent;
+ }
+
+ protected AlphaNodeFieldConstraint[] getAlphaContraints() {
+ return this.alphaConstraints;
+ }
+
+ protected AlphaNodeFieldConstraint[] getBetaContraints() {
+ return this.beta.getConstraints();
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/ConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,35 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Leaps specific conflict resolver provides for separate fact and rule based
+ * conflict resolution
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public interface ConflictResolver
+ extends
+ Serializable {
+ public Comparator getFactConflictResolver();
+
+ public Comparator getRuleConflictResolver();
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactHandleTupleAssembly.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,60 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * To store all references needed to retract a fact
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.WorkingMemory
+ * @see java.beans.PropertyChangeListener
+ * @see java.io.Serializable
+ *
+ */
+
+class FactHandleTupleAssembly {
+ final LeapsTuple tuple;
+
+ final int index;
+
+ final int type;
+
+ public final static int EXISTS = 1;
+
+ public final static int NOT = 2;
+
+ FactHandleTupleAssembly(final int type,
+ final LeapsTuple tuple,
+ final int index) {
+ this.type = type;
+ this.tuple = tuple;
+ this.index = index;
+ }
+
+ protected int getIndex() {
+ return this.index;
+ }
+
+ protected LeapsTuple getTuple() {
+ return this.tuple;
+ }
+
+ public int getType() {
+ return this.type;
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FactTable.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,262 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.PropagationContextImpl;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * Implementation of a container to store data elements used throughout the
+ * leaps. Stores fact handles and companion information - relevant rules
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class FactTable extends Table {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5964698708240814905L;
+
+ /**
+ * positive rules are not complete rules but rather its conditions that
+ * relates by type
+ */
+ private final RuleTable rules;
+
+ /**
+ * dynamic rule management support. used to push facts on stack again after
+ * fireAllRules by working memory and adding of a new rule after that
+ */
+ private boolean reseededStack = false;
+
+ /**
+ * Tuples that are either already on agenda or are very close (missing
+ * exists or have not facts matching)
+ */
+ private final IdentityMap tuples;
+
+ /**
+ * initializes base LeapsTable with appropriate Comparator and positive and
+ * negative rules repositories
+ *
+ * @param factConflictResolver
+ * @param ruleConflictResolver
+ */
+ public FactTable(final ConflictResolver conflictResolver) {
+ super( conflictResolver.getFactConflictResolver() );
+ this.rules = new RuleTable( conflictResolver.getRuleConflictResolver() );
+ this.tuples = new IdentityMap();
+ this.comparator = conflictResolver.getFactConflictResolver();
+ this.notAndExistsHashedTables = new IdentityMap();
+ }
+
+ /**
+ * Add rule
+ *
+ * @param workingMemory
+ * @param ruleHandle
+ */
+ public void addRule(final LeapsWorkingMemory workingMemory,
+ final LeapsRuleHandle ruleHandle) {
+ if ( !this.rules.contains( ruleHandle ) ) {
+ this.rules.add( ruleHandle );
+ // push facts back to stack if needed
+ this.checkAndAddFactsToStack( workingMemory );
+ }
+ }
+
+ /**
+ * Remove rule
+ *
+ * @param ruleHandle
+ */
+ public void removeRule(final LeapsWorkingMemory workingMemory,
+ final LeapsRuleHandle ruleHandle) {
+ this.rules.remove( ruleHandle );
+ // remove tuples that are still there
+ for ( final Iterator it = this.getTuplesIterator(); it.hasNext(); ) {
+ final LeapsTuple tuple = (LeapsTuple) it.next();
+ if ( ruleHandle.getLeapsRule().getRule() == tuple.getLeapsRule().getRule() ) {
+ this.tuples.remove( tuple );
+ }
+ }
+ }
+
+ /**
+ * checks if rule arrived after working memory fireAll event and if no rules
+ * where added since then. Iterates through all facts asserted (and not
+ * retracted, they are not here duh) and adds them to the stack.
+ *
+ * @param working
+ * memory
+ *
+ */
+ private void checkAndAddFactsToStack(final LeapsWorkingMemory workingMemory) {
+ if ( this.reseededStack ) {
+ this.setReseededStack( false );
+
+ final PropagationContextImpl context = new PropagationContextImpl( workingMemory.nextPropagationIdCounter(),
+ PropagationContext.ASSERTION,
+ null,
+ null );
+
+ // let's only add facts below waterline - added before rule is added
+ // rest would be added to stack automatically
+ final DefaultFactHandle startFactHandle = new DefaultFactHandle( workingMemory.getIdLastFireAllAt(),
+ new Object() );
+ for ( final Iterator it = this.iteratorFromPositionToTableStart( startFactHandle,
+ startFactHandle ); it.hasNext(); ) {
+ final LeapsFactHandle handle = (LeapsFactHandle) it.next();
+ workingMemory.pushTokenOnStack( handle,
+ new Token( workingMemory,
+ handle,
+ context ) );
+ }
+ }
+ }
+
+ /**
+ * set indicator if rule was added already after fire all completed
+ *
+ * @param new
+ * value
+ */
+ public void setReseededStack(final boolean reseeded) {
+ this.reseededStack = reseeded;
+ }
+
+ /**
+ * returns an iterator of rule handles to the regular(positive) CEs portions
+ * of rules were type matches this fact table underlying type
+ *
+ * @return iterator of positive rule handles
+ */
+ public Iterator getRulesIterator() {
+ return this.rules.iterator();
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public String toString() {
+ final StringBuffer ret = new StringBuffer();
+
+ for ( final Iterator it = this.iterator(); it.hasNext(); ) {
+ final LeapsFactHandle handle = (LeapsFactHandle) it.next();
+ ret.append( "\n" + handle + "[" + handle.getObject() + "]" );
+ }
+
+ ret.append( "\nTuples :" );
+
+ for ( final Iterator it = this.tuples.values().iterator(); it.hasNext(); ) {
+ ret.append( "\n" + it.next() );
+ }
+
+ ret.append( "\nRules :" );
+
+ for ( final Iterator it = this.rules.iterator(); it.hasNext(); ) {
+ final LeapsRuleHandle handle = (LeapsRuleHandle) it.next();
+ ret.append( "\n\t" + handle.getLeapsRule().getRule().getName() + "[dominant - " + handle.getDominantPosition() + "]" );
+ }
+
+ return ret.toString();
+ }
+
+ protected Iterator getTuplesIterator() {
+ return this.tuples.values().iterator();
+ }
+
+ protected void addTuple(final LeapsTuple tuple) {
+ this.tuples.put( tuple,
+ tuple );
+ }
+
+ protected void removeTuple(final LeapsTuple tuple) {
+ this.tuples.remove( tuple );
+ }
+
+ private final IdentityMap notAndExistsHashedTables;
+
+ private final Comparator comparator;
+
+ public void add(final Object object) {
+ super.add( object );
+ for ( final Iterator it = this.notAndExistsHashedTables.values().iterator(); it.hasNext(); ) {
+ // this will also add link to hash into the leapsfacthandle
+ ((HashedTableComponent) it.next()).add( (LeapsFactHandle) object );
+ }
+ }
+
+ public void remove(final Object object) {
+ super.remove( object );
+ // during modify we need to directly remove facts from participating
+ // hashes because modify can throw us off
+ ((LeapsFactHandle) object).removeFromHash();
+ }
+
+ protected void createHashedSubTable(final ColumnConstraints constraint) {
+ this.notAndExistsHashedTables.put( constraint,
+ new HashedTableComponent( constraint,
+ this.comparator ) );
+ }
+
+ protected TableIterator reverseOrderIterator(final Tuple tuple,
+ final ColumnConstraints constraint) {
+ TableIterator ret = ((HashedTableComponent) this.notAndExistsHashedTables.get( constraint )).reverseOrderIterator( tuple );
+ if ( ret == null ) {
+ ret = Table.emptyIterator();
+ }
+ return ret;
+ }
+
+ protected TableIterator iteratorFromPositionToTableStart(final Tuple tuple,
+ final ColumnConstraints constraint,
+ final LeapsFactHandle startFactHandle,
+ final LeapsFactHandle currentFactHandle) {
+ TableIterator ret = ((HashedTableComponent) this.notAndExistsHashedTables.get( constraint )).iteratorFromPositionToTableStart( tuple,
+ startFactHandle,
+ currentFactHandle );
+ if ( ret == null ) {
+ ret = Table.emptyIterator();
+ }
+ return ret;
+ }
+
+ protected TableIterator iteratorFromPositionToTableEnd(final Tuple tuple,
+ final ColumnConstraints constraint,
+ final LeapsFactHandle startFactHandle) {
+ TableIterator ret = ((HashedTableComponent) this.notAndExistsHashedTables.get( constraint )).iteratorFromPositionToTableEnd( tuple,
+ startFactHandle );
+ if ( ret == null ) {
+ ret = Table.emptyIterator();
+ }
+ return ret;
+ }
+
+ protected Iterator getHashedConstraints() {
+ return this.notAndExistsHashedTables.keySet().iterator();
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/FromConstraint.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,24 @@
+package org.drools.leaps;
+
+import java.util.Arrays;
+
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.rule.Column;
+import org.drools.spi.DataProvider;
+
+public class FromConstraint extends ColumnConstraints {
+ private final DataProvider provider;
+
+ public FromConstraint(final Column column,
+ final DataProvider provider,
+ final ColumnConstraints constraints) {
+ super( column,
+ (constraints.getAlphaContraints() == null || constraints.getAlphaContraints().length == 0) ? Arrays.asList( new FromConstraint[0] ) : Arrays.asList( constraints.getAlphaContraints() ),
+ new DefaultBetaConstraints( constraints.getBetaContraints() ) );
+ this.provider = provider;
+ }
+
+ public DataProvider getProvider() {
+ return this.provider;
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/HashedTableComponent.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,147 @@
+package org.drools.leaps;
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.drools.base.evaluators.Operator;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.Declaration;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.Tuple;
+
+public class HashedTableComponent
+ implements
+ Serializable {
+ private final ColumnConstraints constraints;
+
+ private final int numberOfVariableConstraints;
+
+ private final Map buckets;
+
+ private final Comparator comparator;
+
+ private final static Integer DEFAULT_HASH = new Integer( 0 );
+
+ private final Table noConstraintsTable;
+
+ public HashedTableComponent(final ColumnConstraints constraints,
+ final Comparator comparator) {
+ this.constraints = constraints;
+ this.comparator = comparator;
+ this.buckets = new HashMap();
+ this.numberOfVariableConstraints = this.constraints.getBetaContraints().length;
+ this.noConstraintsTable = new Table( this.comparator );
+ }
+
+ public void add(final LeapsFactHandle factHandle) {
+ final Table table = this.getTable( factHandle );
+ if ( table != null ) {
+ table.add( factHandle );
+ factHandle.addHash( table );
+ }
+ }
+
+ public TableIterator reverseOrderIterator(final Tuple tuple) {
+ final Table table = this.getTable( tuple );
+ if ( table != null ) {
+ return table.reverseOrderIterator();
+ } else {
+ return null;
+ }
+ }
+
+ public TableIterator iteratorFromPositionToTableEnd(final Tuple tuple,
+ final LeapsFactHandle startFactHandle) {
+ final Table table = this.getTable( tuple );
+ if ( table != null ) {
+ return table.iteratorFromPositionToTableEnd( startFactHandle );
+ } else {
+ return null;
+ }
+ }
+
+ public TableIterator iteratorFromPositionToTableStart(final Tuple tuple,
+ final LeapsFactHandle startFactHandle,
+ final LeapsFactHandle currentFactHandle) {
+ final Table table = this.getTable( tuple );
+ if ( table != null ) {
+ return table.iteratorFromPositionToTableStart( startFactHandle,
+ currentFactHandle );
+ } else {
+ return null;
+ }
+ }
+
+ private Table getTable(final Tuple tuple) {
+ Table ret = null;
+ if ( this.numberOfVariableConstraints > 0 ) {
+ Map currentMap = this.buckets;
+ for ( int i = 0; (i < this.numberOfVariableConstraints) && (currentMap != null); i++ ) {
+ Integer hash = HashedTableComponent.DEFAULT_HASH;
+ if ( this.constraints.getBetaContraints()[i] instanceof VariableConstraint && ((VariableConstraint) this.constraints.getBetaContraints()[i]).getEvaluator().getOperator() == Operator.EQUAL ) {
+ final Declaration declaration = this.constraints.getBetaContraints()[i].getRequiredDeclarations()[0];
+ final Object select = declaration.getValue( tuple.get( declaration.getColumn().getFactIndex() ).getObject() );
+ if ( select != null ) {
+ hash = new Integer( select.hashCode() );
+ }
+ }
+ // put facts at the very bottom / last instance
+ if ( i != (this.numberOfVariableConstraints - 1) ) {
+ // we can not have null as a value to the key
+ currentMap = (Map) currentMap.get( hash );
+ } else {
+ ret = (Table) currentMap.get( hash );
+ }
+ }
+ } else {
+ ret = this.noConstraintsTable;
+ }
+ return ret;
+ }
+
+ private Table getTable(final LeapsFactHandle factHandle) {
+ Table ret = null;
+ Map currentMap = this.buckets;
+ if ( this.constraints.isAllowedAlpha( factHandle,
+ null,
+ null ) ) {
+ if ( this.numberOfVariableConstraints > 0 ) {
+ for ( int i = 0; i < this.numberOfVariableConstraints; i++ ) {
+ Integer hash = HashedTableComponent.DEFAULT_HASH;
+ if ( this.constraints.getBetaContraints()[i] instanceof VariableConstraint && ((VariableConstraint) this.constraints.getBetaContraints()[i]).getEvaluator().getOperator() == Operator.EQUAL ) {
+ final Object select = ((VariableConstraint) this.constraints.getBetaContraints()[i]).getFieldExtractor().getValue( factHandle.getObject() );
+ if ( select != null ) {
+ hash = new Integer( select.hashCode() );
+ }
+ }
+ // put facts at the very bottom / last instance
+ if ( i != (this.numberOfVariableConstraints - 1) ) {
+ // we can not have null as a value to the key
+ Map map = (Map) currentMap.get( hash );
+ if ( map == null ) {
+ map = new HashMap();
+ currentMap.put( hash,
+ map );
+ }
+ currentMap = map;
+ } else {
+ Table table = (Table) currentMap.get( hash );
+ if ( table == null ) {
+ table = new Table( this.comparator );
+ currentMap.put( hash,
+ table );
+ }
+ ret = table;
+ }
+ }
+ } else {
+ return this.noConstraintsTable;
+ }
+ }
+ return ret;
+ }
+
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsAgenda.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,67 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.List;
+
+import org.drools.common.DefaultAgenda;
+import org.drools.rule.Query;
+import org.drools.spi.Activation;
+import org.drools.spi.ConsequenceException;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsAgenda extends DefaultAgenda {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7985611305408622557L;
+
+ private LeapsWorkingMemory workingMemory;
+
+ public LeapsAgenda(final LeapsWorkingMemory workingMemory) {
+ super( workingMemory );
+ this.workingMemory = workingMemory;
+ }
+
+ public synchronized void fireActivation(final Activation activation) throws ConsequenceException {
+ if ( activation.getRule() instanceof Query ) {
+ // put query results to the working memory location
+ this.workingMemory.addToQueryResults( activation.getRule().getName(),
+ activation.getTuple() );
+ } else {
+ // fire regular rule
+ super.fireActivation( activation );
+ ((LeapsTuple) activation.getTuple()).setWasFired( true );
+ }
+ }
+
+ /**
+ * to accomodate the difference between rete and leaps in storing
+ * activations. we pull activations from rule to activations map we store in
+ * working memory to facilitate activations removal when rule is removed
+ * from the memory
+ *
+ */
+ public Activation[] getActivations() {
+ final List list = this.workingMemory.getActivations();
+ return (Activation[]) list.toArray( new Activation[list.size()] );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsBuilder.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,259 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.base.ClassObjectType;
+import org.drools.common.BetaConstraints;
+import org.drools.common.DefaultBetaConstraints;
+import org.drools.facttemplates.FactTemplateObjectType;
+import org.drools.rule.And;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Exists;
+import org.drools.rule.From;
+import org.drools.rule.GroupElement;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Not;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.ObjectType;
+
+/**
+ * A Rule<code>Builder</code> to process <code>Rule</code>s for use with
+ * Leaps WorkingMemories. Produces list of Leaps rules that wrap Rule and can be
+ * used in Leaps algorithm. All methods are static
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class LeapsBuilder {
+ /**
+ * follows RETEOO logic flow but returns leaps rules list
+ *
+ * @param rule
+ * @return list of leaps rule
+ * @throws InvalidPatternException
+ */
+ final protected static List processRule(final Rule rule) throws InvalidPatternException {
+ final ArrayList leapsRules = new ArrayList();
+ final And[] and = rule.getTransformedLhs();
+ for ( int i = 0, length = and.length; i < length; i++ ) {
+ leapsRules.addAll( processRuleForAnd( and[i],
+ rule ) );
+ }
+ return leapsRules;
+ }
+
+ /**
+ * Creates list of leaps rules for each individual And
+ *
+ * @param and
+ * @param rule
+ * @return list of leaps rules for the given And
+ */
+ final private static List processRuleForAnd(final And and,
+ final Rule rule) {
+ ColumnConstraints constraints;
+ final ArrayList leapsRules = new ArrayList();
+ final ArrayList cols = new ArrayList();
+ final ArrayList notCols = new ArrayList();
+ final ArrayList existsCols = new ArrayList();
+ final ArrayList evalConditions = new ArrayList();
+ for ( final Iterator it = and.getChildren().iterator(); it.hasNext(); ) {
+ final Object object = it.next();
+ if ( object instanceof EvalCondition ) {
+ final EvalCondition eval = (EvalCondition) object;
+ evalConditions.add( eval );
+ } else {
+ if ( object instanceof Column ) {
+ constraints = LeapsBuilder.processColumn( (Column) object );
+ // create column constraints
+ } else if ( object instanceof From ) {
+ constraints = LeapsBuilder.processColumn( ((From) object).getColumn() );
+ } else {
+ // NOTS and EXISTS
+ GroupElement ce = (GroupElement) object;
+ while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
+ ce = (GroupElement) ce.getChildren().get( 0 );
+ }
+ constraints = LeapsBuilder.processColumn( (Column) ce.getChildren().get( 0 ) );
+ }
+ if ( object.getClass() == Not.class ) {
+ notCols.add( constraints );
+ } else if ( object.getClass() == Exists.class ) {
+ existsCols.add( constraints );
+ } else if ( object.getClass() == From.class ) {
+ cols.add( new FromConstraint( ((From) object).getColumn(),
+ ((From) object).getDataProvider(),
+ constraints ) );
+ } else {
+ cols.add( constraints );
+ }
+ }
+ }
+
+ // check eval for presence of required declarations
+ checkEvalUnboundDeclarations( rule,
+ evalConditions );
+ //
+ leapsRules.add( new LeapsRule( rule,
+ cols,
+ notCols,
+ existsCols,
+ evalConditions ) );
+
+ return leapsRules;
+ }
+
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ static void checkEvalUnboundDeclarations(final Rule rule,
+ final ArrayList evals) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( final Iterator it = evals.iterator(); it.hasNext(); ) {
+ final EvalCondition ec = (EvalCondition) it.next();
+ final Declaration[] declarations = ec.getRequiredDeclarations();
+ for ( int i = 0, length = declarations.length; i < length; i++ ) {
+ if ( rule.getDeclaration( declarations[i].getIdentifier() ) == null ) {
+ list.add( declarations[i].getIdentifier() );
+ }
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+ }
+
+ /**
+ * extracts column specific constraints and packages it into
+ * <code>ColumnConstraints</code>
+ *
+ * @param column
+ * @param and
+ * @return leaps packaged ColumnConstraints
+ */
+ final private static ColumnConstraints processColumn(final Column column) {
+ BetaConstraints binder;
+ final List alphaConstraints = new ArrayList();
+ final List predicateConstraints = new ArrayList();
+
+ final List constraints = column.getConstraints();
+
+ final Map declarations = new HashMap();
+
+ if ( column.getDeclaration() != null ) {
+ final Declaration declaration = column.getDeclaration();
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier(),
+ declaration );
+ }
+
+ for ( final Iterator it = constraints.iterator(); it.hasNext(); ) {
+ final Object object = it.next();
+ // Check if its a declaration
+ if ( object instanceof Declaration ) {
+ final Declaration declaration = (Declaration) object;
+ // Add the declaration the map of previously bound declarations
+ declarations.put( declaration.getIdentifier(),
+ declaration );
+ continue;
+ }
+
+ final AlphaNodeFieldConstraint fieldConstraint = (AlphaNodeFieldConstraint) object;
+ if ( fieldConstraint.getRequiredDeclarations().length == 0 ) {
+ alphaConstraints.add( fieldConstraint );
+ } else {
+ predicateConstraints.add( fieldConstraint );
+ }
+ }
+
+ if ( !predicateConstraints.isEmpty() ) {
+ binder = new DefaultBetaConstraints( (AlphaNodeFieldConstraint[]) predicateConstraints.toArray( new AlphaNodeFieldConstraint[predicateConstraints.size()] ) );
+ } else {
+ binder = new DefaultBetaConstraints();
+ }
+
+ return new ColumnConstraints( column,
+ alphaConstraints,
+ binder );
+ }
+
+ /**
+ * Make sure the required declarations are previously bound
+ *
+ * @param declarations
+ * @throws InvalidPatternException
+ */
+ private static void checkUnboundDeclarations(final Map declarations,
+ final Declaration[] requiredDeclarations) throws InvalidPatternException {
+ final List list = new ArrayList();
+ for ( int i = 0, length = requiredDeclarations.length; i < length; i++ ) {
+ if ( declarations.get( requiredDeclarations[i].getIdentifier() ) == null ) {
+ list.add( requiredDeclarations[i].getIdentifier() );
+ }
+ }
+
+ // Make sure the required declarations
+ if ( list.size() != 0 ) {
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append( list.get( 0 ) );
+ for ( int i = 1, size = list.size(); i < size; i++ ) {
+ buffer.append( ", " + list.get( i ) );
+ }
+
+ throw new InvalidPatternException( "Required Declarations not bound: '" + buffer );
+ }
+
+ }
+
+ public static Object getLeapsClassType(final Object o) {
+ if ( o instanceof org.drools.facttemplates.Fact ) {
+ return ((org.drools.facttemplates.Fact) o).getFactTemplate().getName();
+ } else {
+ return o.getClass();
+ }
+ }
+
+ public static Object getLeapsClassType(final ObjectType ot) {
+ if ( ot.getClass() == FactTemplateObjectType.class ) {
+ return ((FactTemplateObjectType) ot).getFactTemplate().getName();
+ } else {
+ // we assume that it's classobject type
+ return ((ClassObjectType) ot).getClassType();
+ }
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandle.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,123 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.leaps.util.Table;
+
+/**
+ * class container for each object asserted / retracted into the system
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsFactHandle extends DefaultFactHandle {
+
+ private List activatedTuples = null;
+
+ private List notTuples = null;
+
+ private List existsTuples = null;
+
+ public LeapsFactHandle(final long id,
+ final Object object) {
+ super( id,
+ object );
+ }
+
+ protected void addActivatedTuple(final LeapsTuple tuple) {
+ if ( this.activatedTuples == null ) {
+ this.activatedTuples = new LinkedList();
+ }
+ this.activatedTuples.add( tuple );
+ }
+
+ protected void addNotTuple(final LeapsTuple tuple,
+ final int index) {
+ if ( this.notTuples == null ) {
+ this.notTuples = new LinkedList();
+ }
+ this.notTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.NOT,
+ tuple,
+ index ) );
+ }
+
+ protected void addExistsTuple(final LeapsTuple tuple,
+ final int index) {
+ if ( this.existsTuples == null ) {
+ this.existsTuples = new LinkedList();
+ }
+ this.existsTuples.add( new FactHandleTupleAssembly( FactHandleTupleAssembly.EXISTS,
+ tuple,
+ index ) );
+ }
+
+ protected Iterator getActivatedTuples() {
+ if ( this.activatedTuples != null ) {
+ return this.activatedTuples.iterator();
+ }
+ return null;
+ }
+
+ protected Iterator getNotTupleAssemblies() {
+ if ( this.notTuples != null ) {
+ return this.notTuples.iterator();
+ }
+ return null;
+ }
+
+ protected Iterator getExistsTupleAssemblies() {
+ if ( this.existsTuples != null ) {
+ return this.existsTuples.iterator();
+ }
+ return null;
+ }
+
+ protected void clearActivatedTuples() {
+ this.activatedTuples = null;
+ }
+
+ protected void clearExistsTuples() {
+ this.existsTuples = null;
+ }
+
+ protected void clearNotTuples() {
+ this.notTuples = null;
+ }
+
+ private LinkedList hashes = null;
+
+ protected void addHash(final Table table) {
+ if ( this.hashes == null ) {
+ this.hashes = new LinkedList();
+ }
+ this.hashes.add( table );
+ }
+
+ protected void removeFromHash() {
+ if ( this.hashes != null ) {
+ for ( final Iterator it = this.hashes.iterator(); it.hasNext(); ) {
+ ((Table) it.next()).remove( this );
+ }
+ this.hashes.clear();
+ }
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsFactHandleFactory.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,97 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.EqualityKey;
+import org.drools.common.InternalFactHandle;
+import org.drools.spi.FactHandleFactory;
+
+/**
+ * @author Alexander Bagerman
+ *
+ */
+class LeapsFactHandleFactory
+ implements
+ FactHandleFactory {
+ private static final long serialVersionUID = 8510623248591449450L;
+
+ private long counter;
+
+ protected LeapsFactHandleFactory() {
+ this.counter = 0L;
+ }
+
+ /**
+ * it does not make sense in leaps context. so we generate fact handle as we
+ * did with no counter supplied
+ *
+ * @see org.drools.reteoo.FactHandleFactory
+ */
+ public final InternalFactHandle newFactHandle(final Object object) {
+ return new LeapsFactHandle( this.getNextId(),
+ object );
+ }
+
+ /**
+ * leaps handle
+ *
+ * @param object
+ * @return leaps handle
+ */
+ public final InternalFactHandle newFactHandle(final long newId,
+ final Object object) {
+ return newFactHandle( object );
+ }
+
+ /**
+ *
+ * @return incremented id
+ */
+ protected synchronized long getNextId() {
+ return ++this.counter;
+ }
+
+ /**
+ * the same as in rete
+ *
+ * @see org.drools.reteoo.FactHandleFactory
+ */
+ public final void increaseFactHandleRecency(final InternalFactHandle factHandle) {
+ factHandle.setRecency( this.getNextId() );
+ }
+
+ /**
+ * instead of destroying we put EqualityKey back there
+ * because of the nature of Leaps processing delayed actions
+ *
+ * @see org.drools.reteoo.FactHandleFactory
+ */
+ public void destroyFactHandle(final InternalFactHandle factHandle) {
+ factHandle.setEqualityKey( new EqualityKey( factHandle ) );
+ }
+
+ /**
+ * @see org.drools.reteoo.FactHandleFactory
+ */
+ public FactHandleFactory newInstance() {
+ return new LeapsFactHandleFactory();
+ }
+
+ public Class getFactHandleType() {
+ return LeapsFactHandle.class;
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResult.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,62 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.FactHandle;
+import org.drools.QueryResult;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+
+public class LeapsQueryResult extends QueryResult {
+ public LeapsQueryResult(final Tuple tuple,
+ final WorkingMemory workingMemory,
+ final QueryResults queryResults) {
+ super( tuple,
+ workingMemory,
+ queryResults );
+ }
+
+ public Object get(final int i) {
+ // adjust for the DroolsQuery object
+ return super.get( i - 1 );
+ }
+
+ public FactHandle[] getFactHandles() {
+ // Strip the DroolsQuery fact
+ final FactHandle[] src = super.tuple.getFactHandles();
+ final FactHandle[] dst = new FactHandle[src.length - 1];
+ System.arraycopy( src,
+ 0,
+ dst,
+ 0,
+ dst.length );
+ return dst;
+ }
+
+ public int size() {
+ // Adjust for the DroolsQuery object
+ return super.size() + 1;
+ }
+
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsQueryResults.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,82 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.drools.QueryResult;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.rule.Query;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+
+public class LeapsQueryResults extends QueryResults {
+
+ public LeapsQueryResults(final List results,
+ final Query query,
+ final WorkingMemory workingMemory) {
+ super( results,
+ query,
+ workingMemory );
+ }
+
+ public QueryResult get(final int i) {
+ if ( i > this.results.size() ) {
+ throw new NoSuchElementException();
+ }
+ return new LeapsQueryResult( (Tuple) this.results.get( i ),
+ this.workingMemory,
+ this );
+ }
+
+ public Iterator iterator() {
+ return new QueryResultsIterator( this.results.iterator() );
+ }
+
+ class QueryResultsIterator
+ implements
+ Iterator {
+ private Iterator iterator;
+
+ public QueryResultsIterator(final Iterator iterator) {
+ this.iterator = iterator;
+ }
+
+ public boolean hasNext() {
+ return this.iterator.hasNext();
+ }
+
+ public Object next() {
+ return new LeapsQueryResult( (Tuple) this.iterator.next(),
+ LeapsQueryResults.this.workingMemory,
+ LeapsQueryResults.this );
+ }
+
+ public void remove() {
+ this.iterator.remove();
+ }
+
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRule.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,161 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import org.drools.common.AgendaGroupImpl;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.Rule;
+
+/**
+ * Wrapper class to drools generic rule to extract matching elements from it to
+ * use during leaps iterations.
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class LeapsRule
+ implements
+ Serializable {
+ Rule rule;
+
+ final ColumnConstraints[] columnConstraints;
+
+ final ColumnConstraints[] notColumnConstraints;
+
+ final ColumnConstraints[] existsColumnConstraints;
+
+ final EvalCondition[] evalConditions;
+
+ boolean notColumnsPresent;
+
+ boolean existsColumnsPresent;
+
+ boolean evalCoditionsPresent;
+
+ final Class[] existsNotsClasses;
+
+ public LeapsRule(final Rule rule,
+ final ArrayList columns,
+ final ArrayList notColumns,
+ final ArrayList existsColumns,
+ final ArrayList evalConditions) {
+ this.rule = rule;
+ this.columnConstraints = (ColumnConstraints[]) columns.toArray( new ColumnConstraints[0] );
+ this.notColumnConstraints = (ColumnConstraints[]) notColumns.toArray( new ColumnConstraints[0] );
+ this.existsColumnConstraints = (ColumnConstraints[]) existsColumns.toArray( new ColumnConstraints[0] );
+ this.evalConditions = (EvalCondition[]) evalConditions.toArray( new EvalCondition[0] );
+ this.notColumnsPresent = (this.notColumnConstraints.length != 0);
+ this.existsColumnsPresent = (this.existsColumnConstraints.length != 0);
+ this.evalCoditionsPresent = (this.evalConditions.length != 0);
+
+ final ArrayList classes = new ArrayList();
+ for ( int i = 0; i < this.notColumnConstraints.length; i++ ) {
+ if ( !classes.contains( this.notColumnConstraints[i].getClassType() ) ) {
+ classes.add( this.notColumnConstraints[i].getClassType() );
+ }
+ }
+ for ( int i = 0; i < this.existsColumnConstraints.length; i++ ) {
+ if ( !classes.contains( this.existsColumnConstraints[i].getClassType() ) ) {
+ classes.add( this.existsColumnConstraints[i].getClassType() );
+ }
+ }
+
+ this.existsNotsClasses = (Class[]) classes.toArray( new Class[0] );
+ }
+
+ Rule getRule() {
+ return this.rule;
+ }
+
+ int getNumberOfColumns() {
+ return this.columnConstraints.length;
+ }
+
+ int getNumberOfNotColumns() {
+ return this.notColumnConstraints.length;
+ }
+
+ int getNumberOfExistsColumns() {
+ return this.existsColumnConstraints.length;
+ }
+
+ int getNumberOfEvalConditions() {
+ return this.evalConditions.length;
+ }
+
+ Object getColumnClassObjectTypeAtPosition(final int idx) {
+ return this.columnConstraints[idx].getClassType();
+ }
+
+ ColumnConstraints getColumnConstraintsAtPosition(final int idx) {
+ return this.columnConstraints[idx];
+ }
+
+ ColumnConstraints[] getNotColumnConstraints() {
+ return this.notColumnConstraints;
+ }
+
+ ColumnConstraints[] getExistsColumnConstraints() {
+ return this.existsColumnConstraints;
+ }
+
+ EvalCondition[] getEvalConditions() {
+ return this.evalConditions;
+ }
+
+ boolean containsNotColumns() {
+ return this.notColumnsPresent;
+ }
+
+ boolean containsExistsColumns() {
+ return this.existsColumnsPresent;
+ }
+
+ boolean containsEvalConditions() {
+ return this.evalCoditionsPresent;
+ }
+
+ public int hashCode() {
+ return this.rule.hashCode();
+ }
+
+ public boolean equals(final Object that) {
+ return this == that;
+ }
+
+ Class[] getExistsNotColumnsClasses() {
+ return this.existsNotsClasses;
+ }
+
+ /**
+ * to simulate terminal node memory we introduce
+ * TerminalNodeMemory type attributes here
+ *
+ */
+ private AgendaGroupImpl agendaGroup;
+
+ public AgendaGroupImpl getAgendaGroup() {
+ return this.agendaGroup;
+ }
+
+ public void setAgendaGroup(final AgendaGroupImpl agendaGroup) {
+ this.agendaGroup = agendaGroup;
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleBase.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,205 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.PackageIntegrationException;
+import org.drools.RuleBase;
+import org.drools.RuleBaseConfiguration;
+import org.drools.WorkingMemory;
+import org.drools.common.AbstractRuleBase;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.rule.InvalidPatternException;
+import org.drools.rule.Rule;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.PropagationContext;
+
+/**
+ * This base class for the engine and analogous to Drool's RuleBase class. It
+ * has a similar interface adapted to the Leaps algorithm
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsRuleBase extends AbstractRuleBase {
+ private static final long serialVersionUID = 1487738104393155409L;
+
+ private Map leapsRules;
+
+ /**
+ * Default constructor - for Externalizable. This should never be used by a user, as it
+ * will result in an invalid state for the instance.
+ */
+ public LeapsRuleBase() {
+
+ }
+
+ /**
+ * Construct.
+ *
+ * @param rete
+ * The rete network.
+ */
+ public LeapsRuleBase(final String id) {
+ this( id,
+ null,
+ new LeapsFactHandleFactory() );
+ }
+
+ /**
+ * Construct.
+ *
+ * @param rete
+ * The rete network.
+ * @param conflictResolver
+ * The conflict resolver.
+ * @param factHandleFactory
+ * The fact handle factory.
+ * @param pkgs
+ * @param applicationData
+ * @throws PackageIntegrationException
+ * @throws Exception
+ */
+ public LeapsRuleBase(final String id,
+ final RuleBaseConfiguration config,
+ final FactHandleFactory factHandleFactory) {
+ super( id,
+ config,
+ factHandleFactory );
+ this.leapsRules = new HashMap();
+ }
+
+ /**
+ * @see RuleBase
+ */
+ public WorkingMemory newWorkingMemory() {
+ return newWorkingMemory( true );
+ }
+
+ /**
+ * @see RuleBase
+ */
+ public WorkingMemory newWorkingMemory(final boolean keepReference) {
+ final LeapsWorkingMemory workingMemory = new LeapsWorkingMemory( this.workingMemoryCounter++,
+ this );
+ // add all rules added so far
+ for ( final Iterator it = this.leapsRules.values().iterator(); it.hasNext(); ) {
+ workingMemory.addLeapsRules( (List) it.next() );
+ }
+ //
+ super.addWorkingMemory( workingMemory,
+ keepReference );
+
+ return workingMemory;
+ }
+
+ /**
+ * Creates leaps rule wrappers and propagate rule to the working memories
+ *
+ * @param rule
+ * @throws FactException
+ * @throws InvalidPatternException
+ */
+ public void addRule(final Rule rule) throws FactException,
+ InvalidPatternException {
+ // checks rule validity
+ super.addRule( rule );
+
+ final List rules = LeapsBuilder.processRule( rule );
+
+ this.leapsRules.put( rule,
+ rules );
+
+ for ( final Iterator it = this.getWorkingMemories().iterator(); it.hasNext(); ) {
+ ((LeapsWorkingMemory) it.next()).addLeapsRules( rules );
+ }
+
+ // Iterate each workingMemory and attempt to fire any rules, that were
+ // activated as a result of the new rule addition
+ // abstract rule base does it
+ }
+
+ public void removeRule(final Rule rule) {
+ for ( final Iterator it = this.getWorkingMemories().iterator(); it.hasNext(); ) {
+ ((LeapsWorkingMemory) it.next()).removeRule( (List) this.leapsRules.remove( rule ) );
+ }
+ }
+
+ /**
+ * Handles the write serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+ * The Package uses PackageCompilationData to hold a reference to the generated bytecode. The generated bytecode must be restored before any Rules.
+ *
+ */
+ public void writeExternal(final ObjectOutput stream) throws IOException {
+ doWriteExternal( stream,
+ new Object[0] );
+ }
+
+ /**
+ * Handles the read serialization of the Package. Patterns in Rules may reference generated data which cannot be serialized by default methods.
+ * The Package uses PackageCompilationData to hold a reference to the generated bytecode; which must be restored before any Rules.
+ * A custom ObjectInputStream, able to resolve classes against the bytecode in the PackageCompilationData, is used to restore the Rules.
+ *
+ */
+ public void readExternal(final ObjectInput stream) throws IOException,
+ ClassNotFoundException {
+ doReadExternal( stream,
+ new Object[0] );
+
+ this.leapsRules = new HashMap();
+
+ for ( int i = 0; i < this.getPackages().length; i++ ) {
+ final Rule[] rules = this.getPackages()[i].getRules();
+
+ for ( int j = 0; j < rules.length; ++j ) {
+ addRule( rules[j] );
+ }
+ }
+ }
+
+ public void assertObject(final FactHandle handle,
+ final Object object,
+ final PropagationContext context,
+ final ReteooWorkingMemory workingMemory) throws FactException {
+ // do nothing as reteoo specific
+
+ }
+
+ public void modifyObject(final FactHandle handle,
+ final PropagationContext context,
+ final ReteooWorkingMemory workingMemory) throws FactException {
+ // do nothing as reteoo specific
+
+ }
+
+ public void retractObject(final FactHandle handle,
+ final PropagationContext context,
+ final ReteooWorkingMemory workingMemory) throws FactException {
+ // do nothing as reteoo specific
+
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsRuleHandle.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,86 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.common.DefaultFactHandle;
+
+/**
+ * class container for rules. Re-using defaultfact handle
+ *
+ * class container for rules used in the system. Handle is created for each
+ * leaps rule, dominant position (column/ce position), dominant position type
+ * (class at the column/ce position) or indicator if handle is for asserted or
+ * retracted tuple combination
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsRuleHandle extends DefaultFactHandle {
+
+ // ce position for which handle is created
+ private final int dominantPosition;
+
+ public LeapsRuleHandle(final long id,
+ final LeapsRule rule,
+ final int dominantPosition) {
+ super( id,
+ rule );
+ this.dominantPosition = dominantPosition;
+ }
+
+ /**
+ * @return leaps wrapped rule
+ */
+ public LeapsRule getLeapsRule() {
+ return (LeapsRule) this.getObject();
+ }
+
+ /**
+ * @return base column / ce position
+ */
+ public int getDominantPosition() {
+ return this.dominantPosition;
+ }
+
+ /**
+ * @see org.drools.rule.Rule
+ */
+ public int getRuleComplexity() {
+ return this.getLeapsRule().getRule().getDeclarations().length;
+ }
+
+ /**
+ * @see org.drools.rule.Rule
+ */
+ public int getSalience() {
+ return this.getLeapsRule().getRule().getSalience();
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public boolean equals(final Object that) {
+ return super.equals( that ) && (this.getDominantPosition() == ((LeapsRuleHandle) that).getDominantPosition());
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public String toString() {
+ return "R-" + this.getId() + " \"" + this.getLeapsRule().toString() + "\" [pos - " + this.dominantPosition + "]";
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsTuple.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,285 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+import org.drools.FactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * Leaps Tuple implementation
+ *
+ * @author Alexander Bagerman
+ */
+class LeapsTuple
+ implements
+ Tuple,
+ Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private PropagationContext context;
+
+ private boolean readyForActivation;
+
+ private final LeapsFactHandle[] factHandles;
+
+ private LeapsFactHandle[] blockingNotFactHandles = null;
+
+ private LeapsFactHandle[] existsFactHandles = null;
+
+ private Activation activation;
+
+ private final LeapsRule leapsRule;
+
+ private boolean wasFired = false;
+
+ /**
+ * agendaItem parts
+ */
+ LeapsTuple(final LeapsFactHandle factHandles[],
+ final LeapsRule leapsRule,
+ final PropagationContext context) {
+ this.factHandles = factHandles;
+ this.leapsRule = leapsRule;
+ this.context = context;
+
+ if ( this.leapsRule != null ) {
+ if ( this.leapsRule.containsNotColumns() ) {
+ this.blockingNotFactHandles = new LeapsFactHandle[this.leapsRule.getNotColumnConstraints().length];
+ for ( int i = 0; i < this.blockingNotFactHandles.length; i++ ) {
+ this.blockingNotFactHandles[i] = null;
+ }
+ }
+ if ( this.leapsRule.containsExistsColumns() ) {
+ this.existsFactHandles = new LeapsFactHandle[this.leapsRule.getExistsColumnConstraints().length];
+ for ( int i = 0; i < this.existsFactHandles.length; i++ ) {
+ this.existsFactHandles[i] = null;
+ }
+ }
+ }
+ this.readyForActivation = (this.leapsRule == null || !this.leapsRule.containsExistsColumns());
+ }
+
+ /**
+ * get rule that caused this tuple to be generated
+ *
+ * @return rule
+ */
+ protected LeapsRule getLeapsRule() {
+ return this.leapsRule;
+ }
+
+ /**
+ * Determine if this tuple depends upon a specified object.
+ *
+ * @param handle
+ * The object handle to test.
+ *
+ * @return <code>true</code> if this tuple depends upon the specified
+ * object, otherwise <code>false</code>.
+ *
+ * @see org.drools.spi.Tuple
+ */
+ public boolean dependsOn(final FactHandle handle) {
+ for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+ if ( handle.equals( this.factHandles[i] ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle get(final int col) {
+ return this.factHandles[col];
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle get(final Declaration declaration) {
+ return this.get( declaration.getColumn().getFactIndex() );
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle[] getFactHandles() {
+ return this.factHandles;
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public void setActivation(final Activation activation) {
+ this.activation = activation;
+ }
+
+ /**
+ * to determine if "active" agendaItem needs to be valid from the queue on
+ * fact retraction
+ *
+ * @return indicator if agendaItem was null'ed
+ */
+ protected boolean isActivationNull() {
+ return this.activation == null;
+ }
+
+ protected Activation getActivation() {
+ return this.activation;
+ }
+
+ public long getRecency() {
+ return 0;
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public boolean equals(final Object object) {
+ if ( this == object ) {
+ return true;
+ }
+
+ if ( object == null || !(object instanceof LeapsTuple) ) {
+ return false;
+ }
+
+ final FactHandle[] thatFactHandles = ((LeapsTuple) object).getFactHandles();
+ if ( thatFactHandles.length != this.factHandles.length ) {
+ return false;
+ }
+
+ for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+ if ( !this.factHandles[i].equals( thatFactHandles[i] ) ) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ /**
+ * indicates if exists conditions complete and there is no blocking facts
+ *
+ * @return
+ */
+ protected boolean isReadyForActivation() {
+ return this.readyForActivation;
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public String toString() {
+ final StringBuffer buffer = new StringBuffer( "LeapsTuple [" + this.leapsRule.getRule().getName() + "] " );
+
+ for ( int i = 0, length = this.factHandles.length; i < length; i++ ) {
+ buffer.append( ((i == 0) ? "" : ", ") + this.factHandles[i] );
+ }
+
+ if ( this.existsFactHandles != null ) {
+ buffer.append( "\nExists fact handles by position" );
+ for ( int i = 0, length = this.existsFactHandles.length; i < length; i++ ) {
+ buffer.append( "\nposition " + i ).append( this.existsFactHandles[i] );
+ }
+ }
+ if ( this.blockingNotFactHandles != null ) {
+ buffer.append( "\nblockingNot fact handles by position" );
+ for ( int i = 0, length = this.blockingNotFactHandles.length; i < length; i++ ) {
+ buffer.append( "\nposition " + i ).append( this.blockingNotFactHandles[i] );
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ protected void setBlockingNotFactHandle(final LeapsFactHandle factHandle,
+ final int index) {
+ this.readyForActivation = false;
+ this.blockingNotFactHandles[index] = factHandle;
+ }
+
+ protected boolean isBlockingNotFactHandle(final int index) {
+ return this.blockingNotFactHandles[index] != null;
+ }
+
+ protected void removeBlockingNotFactHandle(final int index) {
+ this.blockingNotFactHandles[index] = null;
+ this.setReadyForActivation();
+ }
+
+ protected void setExistsFactHandle(final LeapsFactHandle factHandle,
+ final int index) {
+ this.existsFactHandles[index] = factHandle;
+ this.setReadyForActivation();
+ }
+
+ protected boolean isExistsFactHandle(final int index) {
+ return this.existsFactHandles[index] != null;
+ }
+
+ protected void removeExistsFactHandle(final int index) {
+ this.existsFactHandles[index] = null;
+ this.setReadyForActivation();
+ }
+
+ private void setReadyForActivation() {
+ this.readyForActivation = true;
+
+ if ( this.blockingNotFactHandles != null ) {
+ for ( int i = 0, length = this.blockingNotFactHandles.length; i < length; i++ ) {
+ if ( this.blockingNotFactHandles[i] != null ) {
+ this.readyForActivation = false;
+ return;
+ }
+ }
+ }
+
+ if ( this.existsFactHandles != null ) {
+ for ( int i = 0, length = this.existsFactHandles.length; i < length; i++ ) {
+ if ( this.existsFactHandles[i] == null ) {
+ this.readyForActivation = false;
+ return;
+ }
+ }
+ }
+ }
+
+ protected PropagationContext getContext() {
+ return this.context;
+ }
+
+ protected void setContext(final PropagationContext context) {
+ this.context = context;
+ }
+
+ public boolean isWasFired() {
+ return this.wasFired;
+ }
+
+ public void setWasFired(final boolean wasFired) {
+ this.wasFired = wasFired;
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/LeapsWorkingMemory.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,838 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.PropertyChangeListener;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.map.IdentityMap;
+import org.drools.FactException;
+import org.drools.QueryResults;
+import org.drools.WorkingMemory;
+import org.drools.common.AbstractWorkingMemory;
+import org.drools.common.AgendaGroupImpl;
+import org.drools.common.AgendaItem;
+import org.drools.common.EventSupport;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.ScheduledAgendaItem;
+import org.drools.leaps.conflict.DefaultConflictResolver;
+import org.drools.leaps.util.TokenStack;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaFilter;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.Duration;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+import org.drools.util.IteratorChain;
+
+/**
+ * Followed RETEOO implementation for interfaces.
+ *
+ * This class is a repository for leaps specific containers (fact factTables).
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.WorkingMemory
+ * @see java.beans.PropertyChangeListener
+ * @see java.io.Serializable
+ *
+ */
+class LeapsWorkingMemory extends AbstractWorkingMemory
+ implements
+ EventSupport,
+ PropertyChangeListener {
+ private static final long serialVersionUID = 320;
+
+ private final Map queryResults;
+
+ private final IdentityMap leapsRulesToHandlesMap = new IdentityMap();
+
+ private final IdentityMap rulesActivationsMap = new IdentityMap();
+
+ private final LinkedList noPositiveColumnsRules = new LinkedList();
+
+ /**
+ * Construct.
+ *
+ * @param ruleBase
+ * The backing rule-base.
+ */
+ public LeapsWorkingMemory(final int id,
+ final InternalRuleBase ruleBase) {
+ super( id,
+ ruleBase,
+ ruleBase.newFactHandleFactory() );
+ this.queryResults = new HashMap();
+ this.agenda = new LeapsAgenda( this );
+ }
+
+ public void doAssertObject(final InternalFactHandle factHandle,
+ final Object object,
+ final PropagationContext propagationContext) throws FactException {
+
+ this.pushTokenOnStack( factHandle,
+ new Token( this,
+ factHandle,
+ propagationContext ) );
+
+ // determine what classes it belongs to put it into the "table" on
+ // class name key
+ final List tuplesToAssert = new LinkedList();
+ final Object objectClass = LeapsBuilder.getLeapsClassType( object );
+ for ( final Iterator tables = this.getFactTablesList( objectClass ).iterator(); tables.hasNext(); ) {
+ tuplesToAssert.clear();
+ final FactTable factTable = (FactTable) tables.next();
+ // adding fact to container
+ factTable.add( factHandle );
+ // iterate through unsatisfied exists
+ for ( final Iterator tuples = factTable.getTuplesIterator(); tuples.hasNext(); ) {
+ final LeapsTuple tuple = (LeapsTuple) tuples.next();
+
+ TokenEvaluator.evaluateExistsConditions( tuple,
+ tuple.getLeapsRule(),
+ this );
+ // check and see if we need activate
+ // activate only if tuple was not ready for it before
+ if ( tuple.isReadyForActivation() ) {
+ // ready to activate
+ tuplesToAssert.add( tuple );
+ }
+ }
+ for ( final Iterator it = tuplesToAssert.iterator(); it.hasNext(); ) {
+ // ready to activate
+ final LeapsTuple tuple = (LeapsTuple) it.next();
+ factTable.removeTuple( tuple );
+ tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+ PropagationContext.ASSERTION,
+ tuple.getLeapsRule().getRule(),
+ null ) );
+ this.assertTuple( tuple );
+ }
+ }
+ // inspect all tuples for not conditions and activate
+ // deactivate agenda items
+ final Activation[] activations = this.agenda.getActivations();
+ for ( int k = 0; k < activations.length; k++ ) {
+ boolean deActivate = false;
+ final LeapsTuple tuple = (LeapsTuple) activations[k].getTuple();
+ final ColumnConstraints[] not = tuple.getLeapsRule().getNotColumnConstraints();
+ for ( int i = 0, length = not.length; !deActivate && i < length; i++ ) {
+ final ColumnConstraints constraint = not[i];
+ final Object columnClassObject = constraint.getClassType();
+ if ( ((objectClass.getClass() == Class.class && columnClassObject.getClass() == Class.class && ((Class) columnClassObject).isAssignableFrom( (Class) objectClass )) || (objectClass.getClass() != Class.class
+ && columnClassObject.getClass() != Class.class && columnClassObject.equals( objectClass )))
+ && constraint.isAllowed( factHandle,
+ tuple,
+ this ) ) {
+ tuple.setBlockingNotFactHandle( (LeapsFactHandle) factHandle,
+ i );
+ ((LeapsFactHandle) factHandle).addNotTuple( tuple,
+ i );
+ deActivate = true;
+ }
+ }
+ // check and see if we need de-activate
+ if ( deActivate ) {
+ tuple.setContext( new PropagationContextImpl( nextPropagationIdCounter(),
+ PropagationContext.ASSERTION,
+ tuple.getLeapsRule().getRule(),
+ null ) );
+ if ( tuple.getLeapsRule().getRule() instanceof Query ) {
+ // put query results to the working memory
+ // location
+ removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
+ tuple );
+ } else {
+ // time to pull from agenda
+ invalidateActivation( tuple );
+ }
+ }
+ }
+ }
+
+ /**
+ * copies reteoo behaviour in regards to logical assertion and does checking
+ * on available tuples to see if any needs invalidation / activation as a
+ * result of this retraction
+ *
+ * @see WorkingMemory
+ */
+ public void doRetract(final InternalFactHandle factHandle,
+ final PropagationContext propagationContext) {
+
+ /*
+ * leaps specific actions
+ */
+ // remove fact from all relevant fact tables container
+ final Object objectClass = LeapsBuilder.getLeapsClassType( factHandle.getObject() );
+ for ( final Iterator it = this.getFactTablesList( objectClass ).iterator(); it.hasNext(); ) {
+ ((FactTable) it.next()).remove( factHandle );
+ }
+
+ // 0. remove activated tuples
+ final Iterator tuples = ((LeapsFactHandle) factHandle).getActivatedTuples();
+ for ( ; tuples != null && tuples.hasNext(); ) {
+ final LeapsTuple tuple = (LeapsTuple) tuples.next();
+ if ( tuple.getLeapsRule().getRule() instanceof Query ) {
+ // put query results to the working memory location
+ removeFromQueryResults( tuple.getLeapsRule().getRule().getName(),
+ tuple );
+ } else {
+ // time to pull from agenda
+ invalidateActivation( tuple );
+ }
+ }
+ ((LeapsFactHandle) factHandle).clearActivatedTuples();
+ // assert all tuples that are ready for activation or cancel ones
+ // that are no longer
+ Iterator it;
+ final IteratorChain chain = new IteratorChain();
+ it = ((LeapsFactHandle) factHandle).getNotTupleAssemblies();
+ if ( it != null ) {
+ chain.addIterator( it );
+ }
+ it = ((LeapsFactHandle) factHandle).getExistsTupleAssemblies();
+ if ( it != null ) {
+ chain.addIterator( it );
+ }
+ for ( ; chain.hasNext(); ) {
+ final FactHandleTupleAssembly tupleAssembly = ((FactHandleTupleAssembly) chain.next());
+ final LeapsTuple tuple = tupleAssembly.getTuple();
+ if ( tupleAssembly.getType() == FactHandleTupleAssembly.NOT ) {
+ tuple.removeBlockingNotFactHandle( tupleAssembly.getIndex() );
+ } else {
+ tuple.removeExistsFactHandle( tupleAssembly.getIndex() );
+ }
+ // can assert only tuples that were not eligible for activation
+ // before retraction
+ if ( !TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+ tuple.getLeapsRule(),
+ this ) ) {
+ // deactivate tuple that was activated inside of
+ // processAfterAllPositive
+ // bad design, need to rethink it
+ invalidateActivation( tuple );
+ } else {
+ this.assertTuple( tuple );
+ }
+ }
+ ((LeapsFactHandle) factHandle).clearExistsTuples();
+ ((LeapsFactHandle) factHandle).clearNotTuples();
+ // remove it from stack
+ this.removeTokenFromStack( (LeapsFactHandle) factHandle );
+ }
+
+ /**
+ * used when assertion / retraction adds invalidating conditions that make
+ * tuple ineligible for firing
+ *
+ * @param tuple
+ */
+ private final void invalidateActivation(final LeapsTuple tuple) {
+ final Activation activation = tuple.getActivation();
+ // tuple can already loose activation if another fact or exists fact was retracted
+ // or not fact added
+ if ( activation != null ) {
+ if ( activation.isActivated() ) {
+ activation.remove();
+ this.getAgendaEventSupport().fireActivationCancelled( activation );
+ }
+
+ this.getTruthMaintenanceSystem().removeLogicalDependencies( activation,
+ tuple.getContext(),
+ tuple.getLeapsRule().getRule() );
+ //
+ tuple.setActivation( null );
+ // remove from rule / activaitons map
+ FastMap activations = (FastMap) this.rulesActivationsMap.get( activation.getRule() );
+ if ( activations != null ) {
+ activations.remove( activation );
+ }
+ }
+ }
+
+ /**
+ * ************* leaps section *********************
+ */
+ private long idLastFireAllAt = -1;
+
+ private boolean rulesAddedSinceLastFireAll = false;
+
+ /**
+ * algorithm stack.
+ */
+ private final TokenStack mainStack = new TokenStack();
+
+ /**
+ * generates or just return List of internal factTables that correspond a
+ * class can be used to generate factTables
+ *
+ * @return
+ */
+ protected final List getFactTablesList(final Object objectClass) {
+ final ArrayList list = new ArrayList();
+ if ( objectClass.getClass() == Class.class ) {
+ // interfaces
+ final Class[] interfaces = ((Class) objectClass).getInterfaces();
+ for ( int i = 0; i < interfaces.length; i++ ) {
+ list.add( this.getFactTable( interfaces[i] ) );
+ }
+ // classes
+ Class bufClass = (Class) objectClass;
+ while ( bufClass != null ) {
+ //
+ list.add( this.getFactTable( bufClass ) );
+ // and get the next class on the list
+ bufClass = bufClass.getSuperclass();
+ }
+ } else {
+ list.add( this.getFactTable( objectClass ) );
+ }
+ return list;
+ }
+
+ /**
+ * adds new leaps token on main stack
+ *
+ * @param fact
+ * handle
+ * @param token
+ */
+ protected final void pushTokenOnStack(final InternalFactHandle factHandle,
+ final Token token) {
+ this.mainStack.push( token );
+ }
+
+ /**
+ * removes leaps token on main stack
+ *
+ * @param fact
+ * handle
+ */
+ protected final void removeTokenFromStack(final LeapsFactHandle factHandle) {
+ this.mainStack.remove( factHandle.getId() );
+ }
+
+ /**
+ * gets leaps token from top of stack
+ *
+ * @param fact
+ * handle
+ */
+ protected final Token peekTokenOnTop() {
+ return (Token) this.mainStack.peek();
+ }
+
+ /**
+ * get leaps fact table of specific type (class)
+ *
+ * @param type
+ * of objects
+ * @return fact table of requested class type
+ */
+ protected FactTable getFactTable(final Object objectClass) {
+ FactTable table;
+ if ( this.factTables.containsKey( objectClass ) ) {
+ table = (FactTable) this.factTables.get( objectClass );
+ } else {
+ table = new FactTable( DefaultConflictResolver.getInstance() );
+ this.factTables.put( objectClass,
+ table );
+ // review existing rules and assign to the fact table if needed
+ for ( final Iterator iter = this.leapsRulesToHandlesMap.keySet().iterator(); iter.hasNext(); ) {
+ final LeapsRule leapsRule = (LeapsRule) iter.next();
+ if ( leapsRule.getNumberOfColumns() > 0 ) {
+ final List rulesHandles = (List) this.leapsRulesToHandlesMap.get( leapsRule );
+ for ( final Iterator handles = rulesHandles.iterator(); handles.hasNext(); ) {
+ final LeapsRuleHandle handle = (LeapsRuleHandle) handles.next();
+ final Object columnClassObject = leapsRule.getColumnClassObjectTypeAtPosition( handle.getDominantPosition() );
+ if ( (objectClass.getClass() == Class.class && columnClassObject.getClass() == Class.class && ((Class) columnClassObject).isAssignableFrom( (Class) objectClass ))
+ // on template name
+ || (objectClass.getClass() != Class.class && columnClassObject.getClass() != Class.class && columnClassObject.equals( objectClass )) ) {
+ table.addRule( this,
+ handle );
+ }
+ }
+ }
+ }
+ }
+
+ return table;
+ }
+
+ /**
+ * Add Leaps wrapped rules into the working memory
+ *
+ * @param rules
+ */
+ protected void addLeapsRules(final List rules) {
+ this.getLock().lock();
+ try {
+ this.rulesAddedSinceLastFireAll = true;
+
+ ArrayList ruleHandlesList;
+ LeapsRule rule;
+ LeapsRuleHandle ruleHandle;
+ for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
+ rule = (LeapsRule) it.next();
+ // create hashed entries for not and exists
+ // check for NOT and EXISTS and create new hashed entry
+ ColumnConstraints constraint;
+ for ( int i = 0; i < rule.getNumberOfNotColumns(); i++ ) {
+ constraint = rule.getNotColumnConstraints()[i];
+ this.getFactTable( constraint.getClassType() ).createHashedSubTable( constraint );
+ }
+ for ( int i = 0; i < rule.getNumberOfExistsColumns(); i++ ) {
+ constraint = rule.getExistsColumnConstraints()[i];
+ this.getFactTable( constraint.getClassType() ).createHashedSubTable( constraint );
+ }
+ // some times rules do not have "normal" constraints and only
+ // not and exists
+ if ( rule.getNumberOfColumns() > 0 ) {
+ ruleHandlesList = new ArrayList();
+ for ( int i = 0; i < rule.getNumberOfColumns(); i++ ) {
+ ruleHandle = new LeapsRuleHandle( ((LeapsFactHandleFactory) this.handleFactory).getNextId(),
+ rule,
+ i );
+ //
+ if ( rule.getColumnConstraintsAtPosition( i ).getClass() != FromConstraint.class ) {
+ this.getFactTable( rule.getColumnClassObjectTypeAtPosition( i ) ).addRule( this,
+ ruleHandle );
+ //
+ } else {
+ final FactTable table = this.getFactTable( FromConstraintFactDriver.class );
+ table.addRule( this,
+ ruleHandle );
+ if ( table.isEmpty() ) {
+ this.assertObject( new FromConstraintFactDriver() );
+ }
+ }
+ ruleHandlesList.add( ruleHandle );
+ }
+ this.leapsRulesToHandlesMap.put( rule,
+ ruleHandlesList );
+ } else {
+ this.noPositiveColumnsRules.add( new LeapsRuleHandle( ((LeapsFactHandleFactory) this.handleFactory).getNextId(),
+ rule,
+ 0 ) );
+ }
+ }
+ } finally {
+ this.getLock().unlock();
+ }
+ }
+
+ protected void removeRule(final List rules) {
+ this.getLock().lock();
+ try {
+ ArrayList ruleHandlesList;
+ LeapsRule leapsRule;
+ LeapsRuleHandle ruleHandle;
+ for ( final Iterator it = rules.iterator(); it.hasNext(); ) {
+ leapsRule = (LeapsRule) it.next();
+ // some times rules do not have "normal" constraints and only
+ // not and exists
+ if ( leapsRule.getNumberOfColumns() > 0 ) {
+ ruleHandlesList = (ArrayList) this.leapsRulesToHandlesMap.remove( leapsRule );
+ for ( int i = 0; i < ruleHandlesList.size(); i++ ) {
+ ruleHandle = (LeapsRuleHandle) ruleHandlesList.get( i );
+ //
+ this.getFactTable( leapsRule.getColumnClassObjectTypeAtPosition( i ) ).removeRule( this,
+ ruleHandle );
+ }
+ }
+ //
+ }
+ final Rule rule = ((LeapsRule) rules.get( 0 )).getRule();
+ final FastMap activations = (FastMap) this.rulesActivationsMap.remove( rule );
+ if ( activations != null ) {
+ for ( final Iterator activationsIt = activations.keySet().iterator(); activationsIt.hasNext(); ) {
+ final Activation activation = (Activation) activationsIt.next();
+ ((LeapsTuple) activation.getTuple()).setActivation( null );
+ this.tms.removeLogicalDependencies( activation,
+ activation.getPropagationContext(),
+ rule );
+ }
+ }
+
+ propagateQueuedActions();
+ } finally {
+ this.getLock().unlock();
+ }
+ }
+
+ /**
+ * main loop
+ *
+ */
+ public final synchronized void fireAllRules(final AgendaFilter agendaFilter) throws FactException {
+ // If we're already firing a rule, then it'll pick up
+ // the firing for any other assertObject(..) that get
+ // nested inside, avoiding concurrent-modification
+ // exceptions, depending on code paths of the actions.
+
+ if ( !this.firing ) {
+ try {
+ this.firing = true;
+
+ boolean nothingToProcess = false;
+ while ( !nothingToProcess ) {
+ // check for the initial fact
+ for ( final Iterator rulesIt = this.noPositiveColumnsRules.iterator(); rulesIt.hasNext(); ) {
+ final LeapsRule rule = ((LeapsRuleHandle) rulesIt.next()).getLeapsRule();
+ final PropagationContextImpl context = new PropagationContextImpl( nextPropagationIdCounter(),
+ PropagationContext.ASSERTION,
+ null, //rule.getRule( ),
+ null );
+ final LeapsTuple tuple = new LeapsTuple( new LeapsFactHandle[0],
+ rule,
+ context );
+ if ( TokenEvaluator.processAfterAllPositiveConstraintOk( tuple,
+ rule,
+ this ) ) {
+ this.assertTuple( tuple );
+ }
+
+ }
+ this.noPositiveColumnsRules.clear();
+ // normal rules with required columns
+ while ( !this.mainStack.empty() ) {
+ final Token token = this.peekTokenOnTop();
+ boolean done = false;
+ while ( !done ) {
+ if ( !token.isResume() ) {
+ if ( token.hasNextRuleHandle() ) {
+ token.nextRuleHandle();
+ } else {
+ // we do not pop because something might get
+ // asserted
+ // and placed on hte top of the stack during
+ // firing
+ this.removeTokenFromStack( (LeapsFactHandle) token.getDominantFactHandle() );
+ done = true;
+ }
+ }
+ if ( !done ) {
+ try {
+ // ok. now we have tuple, dominant fact
+ // and
+ // rules and ready to seek to checks if
+ // any
+ // agendaItem
+ // matches on current rule
+ TokenEvaluator.evaluate( token );
+ // something was found so set marks for
+ // resume processing
+ if ( token.getDominantFactHandle() != null ) {
+ if ( token.getDominantFactHandle().getObject().getClass() != FromConstraintFactDriver.class ) {
+ token.setResume( true );
+ }
+ done = true;
+ }
+ } catch ( final NoMatchesFoundException ex ) {
+ token.setResume( false );
+ }
+ }
+ // we put everything on agenda
+ // and if there is no modules or anything like it
+ // it would fire just activated rule
+ while ( this.agenda.fireNextItem( agendaFilter ) ) {
+ ;
+ }
+ }
+ }
+ // pick activations generated by retraction or assert
+ // can generate activations off exists and not pending
+ // tuples
+ while ( this.agenda.fireNextItem( agendaFilter ) ) {
+ ;
+ }
+ if ( this.mainStack.empty() ) {
+ nothingToProcess = true;
+ }
+ }
+ // mark when method was called last time
+ this.rulesAddedSinceLastFireAll = false;
+ this.idLastFireAllAt = ((LeapsFactHandleFactory) this.handleFactory).getNextId();
+ // set all factTables to be reseeded
+ for ( final Iterator it = this.factTables.values().iterator(); it.hasNext(); ) {
+ ((FactTable) it.next()).setReseededStack( true );
+ }
+ // clear table that is used to trigger From constraints
+ this.getFactTable( FromConstraintFactDriver.class ).clear();
+ } finally {
+ this.firing = false;
+ }
+ }
+ }
+
+ protected final boolean isRulesAddedSinceLastFireAll() {
+ return this.rulesAddedSinceLastFireAll;
+ }
+
+ protected final long getIdLastFireAllAt() {
+ return this.idLastFireAllAt;
+ }
+
+ public String toString() {
+ String ret = "";
+ Object key;
+ ret = ret + "\n" + "Working memory";
+ ret = ret + "\n" + "Fact Tables by types:";
+ for ( final Iterator it = this.factTables.keySet().iterator(); it.hasNext(); ) {
+ key = it.next();
+ ret = ret + "\n" + "****************** " + key;
+ ret = ret + ((FactTable) this.factTables.get( key )).toString();
+ }
+ ret = ret + "\n" + "Stack:";
+ for ( final Iterator it = this.mainStack.iterator(); it.hasNext(); ) {
+ ret = ret + "\n" + "\t" + it.next();
+ }
+ return ret;
+ }
+
+ /**
+ * Assert a new <code>Tuple</code>.
+ *
+ * @param tuple
+ * The <code>Tuple</code> being asserted.
+ * @param workingMemory
+ * The working memory seesion.
+ * @throws AssertionException
+ * If an error occurs while asserting.
+ */
+ public final void assertTuple(final LeapsTuple tuple) {
+ final PropagationContext context = tuple.getContext();
+ final Rule rule = tuple.getLeapsRule().getRule();
+ // if the current Rule is no-loop and the origin rule is the same then
+ // return
+ if ( rule.getNoLoop() && rule.equals( context.getRuleOrigin() ) ) {
+ return;
+ }
+ //
+ final Duration dur = rule.getDuration();
+
+ Activation agendaItem;
+ if ( dur != null && dur.getDuration( tuple ) > 0 ) {
+ agendaItem = new ScheduledAgendaItem( context.getPropagationNumber(),
+ tuple,
+ this.agenda,
+ context,
+ rule );
+ this.agenda.scheduleItem( (ScheduledAgendaItem) agendaItem );
+ tuple.setActivation( agendaItem );
+ agendaItem.setActivated( true );
+ this.getAgendaEventSupport().fireActivationCreated( agendaItem );
+ } else {
+ final LeapsRule leapsRule = tuple.getLeapsRule();
+ AgendaGroupImpl agendaGroup = leapsRule.getAgendaGroup();
+ if ( agendaGroup == null ) {
+ if ( rule.getAgendaGroup() == null || rule.getAgendaGroup().equals( "" ) || rule.getAgendaGroup().equals( AgendaGroup.MAIN ) ) {
+ // Is the Rule AgendaGroup undefined? If it is use MAIN,
+ // which is added to the Agenda by default
+ agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( AgendaGroup.MAIN );
+ } else {
+ // AgendaGroup is defined, so try and get the AgendaGroup
+ // from the Agenda
+ agendaGroup = (AgendaGroupImpl) this.agenda.getAgendaGroup( rule.getAgendaGroup() );
+ }
+
+ if ( agendaGroup == null ) {
+ // The AgendaGroup is defined but not yet added to the
+ // Agenda, so create the AgendaGroup and add to the Agenda.
+ agendaGroup = new AgendaGroupImpl( rule.getAgendaGroup() );
+ this.agenda.addAgendaGroup( agendaGroup );
+ }
+
+ leapsRule.setAgendaGroup( agendaGroup );
+ }
+
+ // set the focus if rule autoFocus is true
+ if ( rule.getAutoFocus() ) {
+ this.agenda.setFocus( agendaGroup );
+ }
+
+ agendaItem = new AgendaItem( context.getPropagationNumber(),
+ tuple,
+ context,
+ rule );
+
+ agendaGroup.add( agendaItem );
+
+ tuple.setActivation( agendaItem );
+ agendaItem.setActivated( true );
+ this.getAgendaEventSupport().fireActivationCreated( agendaItem );
+ }
+
+ // retract support
+ final LeapsFactHandle[] factHandles = (LeapsFactHandle[]) tuple.getFactHandles();
+ for ( int i = 0; i < factHandles.length; i++ ) {
+ factHandles[i].addActivatedTuple( tuple );
+ }
+
+ // rules remove support
+ FastMap activations = (FastMap) this.rulesActivationsMap.get( rule );
+ if ( activations == null ) {
+ activations = new FastMap();
+ this.rulesActivationsMap.put( rule,
+ activations );
+ }
+ activations.put( agendaItem,
+ agendaItem );
+ }
+
+ List getActivations() {
+ final List ret = new ArrayList();
+ for ( final Iterator it = this.rulesActivationsMap.values().iterator(); it.hasNext(); ) {
+ ret.addAll( ((FastMap) it.next()).values() );
+ }
+
+ return ret;
+ }
+
+ protected long nextPropagationIdCounter() {
+ return ++this.propagationIdCounter;
+ }
+
+ public QueryResults getQueryResults(final String queryName) {
+ final IdentityMap map = (IdentityMap) this.queryResults.get( queryName );
+ if ( map == null ) {
+ return null;
+ }
+
+ final LinkedList list = new LinkedList();
+ for ( final Iterator it = map.keySet().iterator(); it.hasNext(); ) {
+ list.add( it.next() );
+ }
+ if ( !list.isEmpty() ) {
+ final Query queryRule = (Query) ((LeapsTuple) list.get( 0 )).getLeapsRule().getRule();
+ return new LeapsQueryResults( list,
+ queryRule,
+ this );
+ } else {
+ return null;
+ }
+ }
+
+ void addToQueryResults(final String query,
+ final Tuple tuple) {
+ IdentityMap map = (IdentityMap) this.queryResults.get( query );
+ if ( map == null ) {
+ map = new IdentityMap();
+ this.queryResults.put( query,
+ map );
+ }
+ map.put( tuple,
+ tuple );
+ }
+
+ void removeFromQueryResults(final String query,
+ final Tuple tuple) {
+ final IdentityMap map = (IdentityMap) this.queryResults.get( query );
+ if ( map != null ) {
+ map.remove( tuple );
+ }
+ }
+
+ /**
+ * to store facts to cursor over it
+ */
+ private final Map factTables = new FactTables();
+
+ class FactTables
+ implements
+ Map,
+ Serializable {
+ private final LinkedList tables = new LinkedList();
+
+ private final HashMap map = new HashMap();
+
+ public int size() {
+ return this.tables.size();
+ }
+
+ public void clear() {
+ this.tables.clear();
+ this.map.clear();
+ }
+
+ public boolean isEmpty() {
+ return this.tables.isEmpty();
+ }
+
+ public boolean containsKey(final Object key) {
+ return this.map.containsKey( key );
+ }
+
+ public boolean containsValue(final Object value) {
+ return this.map.containsValue( value );
+ }
+
+ public Collection values() {
+ return this.tables;
+ }
+
+ public void putAll(final Map t) {
+ this.tables.addAll( t.values() );
+ this.map.putAll( t );
+ }
+
+ public Set entrySet() {
+ return this.map.entrySet();
+ }
+
+ public Set keySet() {
+ return this.map.keySet();
+ }
+
+ public Object get(final Object key) {
+ return this.map.get( key );
+
+ }
+
+ public Object remove(final Object key) {
+ final Object ret = this.map.remove( key );
+ this.tables.remove( ret );
+ return ret;
+ }
+
+ public Object put(final Object key,
+ final Object value) {
+ this.tables.add( value );
+ this.map.put( key,
+ value );
+ return value;
+ }
+ }
+
+ private class FromConstraintFactDriver
+ implements
+ Serializable {
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/NoMatchesFoundException.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Exception to facilitate <code>seek</code> process in working memory
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class NoMatchesFoundException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public NoMatchesFoundException() {
+ super();
+ }
+
+ public NoMatchesFoundException(final String msg) {
+ super( msg );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/RuleTable.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,39 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+
+import org.drools.leaps.util.Table;
+
+/**
+ * Implementation of a container to store data elements used throughout the
+ * leaps. Stores rule handles
+ *
+ * @author Alexander Bagerman
+ *
+ */
+class RuleTable extends Table {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1855260276968132243L;
+
+ public RuleTable(final Comparator ruleConflictResolver) {
+ super( ruleConflictResolver );
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/Token.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,256 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Iterator;
+
+import org.drools.FactHandle;
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.Declaration;
+import org.drools.spi.Activation;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * this object wears multiple hats - Tuple and being main element that wraps
+ * fact handle on main leaps stack
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class Token
+ implements
+ Tuple,
+ Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private LeapsWorkingMemory workingMemory;
+
+ private final InternalFactHandle dominantFactHandle;
+
+ private LeapsRuleHandle currentRuleHandle = null;
+
+ private LeapsFactHandle[] currentFactHandles = new LeapsFactHandle[0];
+
+ boolean resume = false;
+
+ private Iterator rules = null;
+
+ private final PropagationContext propagationContext;
+
+ /**
+ *
+ */
+ public Token(final LeapsWorkingMemory workingMemory,
+ final InternalFactHandle factHandle,
+ final PropagationContext propagationContext) {
+ this.workingMemory = workingMemory;
+ this.dominantFactHandle = factHandle;
+ this.propagationContext = propagationContext;
+ }
+
+ private Iterator rulesIterator() {
+ if ( this.rules == null ) {
+ if ( this.dominantFactHandle != null ) {
+ this.rules = this.workingMemory.getFactTable( LeapsBuilder.getLeapsClassType( this.dominantFactHandle.getObject() ) ).getRulesIterator();
+ }
+ }
+ return this.rules;
+ }
+
+ public LeapsRuleHandle nextRuleHandle() {
+ this.currentRuleHandle = (LeapsRuleHandle) this.rules.next();
+ this.currentFactHandles = new LeapsFactHandle[this.currentRuleHandle.getLeapsRule().getNumberOfColumns()];
+ return this.currentRuleHandle;
+ }
+
+ /**
+ *
+ * @param memory
+ * @return indicator if there are more rules
+ */
+
+ public boolean hasNextRuleHandle() {
+ boolean ret = false;
+ if ( this.rulesIterator() != null ) {
+ // starting with calling rulesIterator() to make sure that we picks
+ // rules because fact can be asserted before rules added
+ final long levelId = (this.workingMemory.isRulesAddedSinceLastFireAll()) ? this.workingMemory.getIdLastFireAllAt() : -1;
+
+ if ( this.dominantFactHandle == null || this.dominantFactHandle.getRecency() >= levelId ) {
+ ret = this.rules.hasNext();
+ } else {
+ // then we need to skip rules that have id lower than
+ // workingMemory.idLastFireAllAt
+ boolean done = false;
+ while ( !done ) {
+ if ( this.rules.hasNext() ) {
+ if ( ((LeapsRuleHandle) ((TableIterator) this.rules).peekNext()).getRecency() > levelId ) {
+ ret = true;
+ done = true;
+ } else {
+ this.rules.next();
+ }
+ } else {
+ ret = false;
+ done = true;
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ public int hashCode() {
+ if ( this.dominantFactHandle != null ) {
+ return this.dominantFactHandle.hashCode();
+ } else {
+ return 0;
+ }
+ }
+
+ public void set(final int idx,
+ final LeapsFactHandle factHandle) {
+ this.currentFactHandles[idx] = factHandle;
+ }
+
+ public InternalFactHandle getDominantFactHandle() {
+ return this.dominantFactHandle;
+ }
+
+ public LeapsRuleHandle getCurrentRuleHandle() {
+ return this.currentRuleHandle;
+ }
+
+ public boolean isResume() {
+ return this.resume;
+ }
+
+ public void setResume(final boolean resume) {
+ this.resume = resume;
+ }
+
+ /**
+ * We always have only one Tuple per fact handle hence match on handle id
+ *
+ * @see Object
+ */
+ public boolean equals(final Object that) {
+ return this.dominantFactHandle.getId() == ((Token) that).dominantFactHandle.getId();
+ }
+
+ /**
+ * Retrieve the value at position
+ *
+ * @param position
+ * @return The currently bound <code>Object</code> value.
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle get(final int idx) {
+ return this.currentFactHandles[idx];
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle get(final Declaration declaration) {
+ return this.get( declaration.getColumn().getFactIndex() );
+ }
+
+ /**
+ * @see org.drools.spi.Tuple
+ */
+ public InternalFactHandle[] getFactHandles() {
+ return this.currentFactHandles;
+ }
+
+ public long getRecency() {
+ return 0;
+ }
+
+ /**
+ * Returns a reference to the <code>WorkingMemory</code> associated with
+ * this object.
+ *
+ * @return WorkingMemory
+ */
+ public WorkingMemory getWorkingMemory() {
+ return this.workingMemory;
+ }
+
+ /**
+ * @see java.lang.Object
+ */
+ public String toString() {
+ String ret = "TOKEN [" + this.dominantFactHandle + "]\n" + "\tRULE : " + this.currentRuleHandle + "\n";
+ if ( this.currentFactHandles != null ) {
+ for ( int i = 0, length = this.currentFactHandles.length; i < length; i++ ) {
+ ret = ret + ((i == this.currentRuleHandle.getDominantPosition()) ? "***" : "") + "\t" + i + " -> " + this.currentFactHandles[i].getObject() + "\n";
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * creates lightweight tuple suitable for agendaItem
+ *
+ * @return LeapsTuple
+ */
+ LeapsTuple getTuple() {
+ return new LeapsTuple( this.currentFactHandles,
+ this.currentRuleHandle.getLeapsRule(),
+ this.propagationContext );
+ }
+
+ /**
+ * Determine if this tuple depends upon a specified object.
+ *
+ * @param handle
+ * The object handle to test.
+ *
+ * @return <code>true</code> if this tuple depends upon the specified
+ * object, otherwise <code>false</code>.
+ */
+ public boolean dependsOn(final FactHandle handle) {
+ for ( int i = 0, length = this.currentFactHandles.length; i < length; i++ ) {
+ if ( this.currentFactHandles[i].equals( handle ) ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Do nothing because this tuple never gets to agendaItem stage. Another one -
+ * LeapsTuple - is created to take part in agendaItem processing
+ *
+ * @see getTuple()
+ * @see org.drools.spi.Tuple
+ */
+ public void setActivation(final Activation activation) {
+ // do nothing
+ }
+
+ public PropagationContext getPropagationContext() {
+ return this.propagationContext;
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/TokenEvaluator.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,358 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.InternalFactHandle;
+import org.drools.leaps.util.Table;
+import org.drools.leaps.util.TableIterator;
+import org.drools.rule.EvalCondition;
+import org.drools.rule.InvalidRuleException;
+import org.drools.spi.Tuple;
+
+/**
+ * helper class that does condition evaluation on token when working memory does
+ * seek. all methods are static
+ *
+ * @author Alexander Bagerman
+ *
+ */
+final class TokenEvaluator {
+ /**
+ * this method does nested loops iterations on all relavant fact tables and
+ * evaluates rules conditions
+ *
+ * @param token
+ * @throws NoMatchesFoundException
+ * @throws Exception
+ * @throws InvalidRuleException
+ */
+ final static protected void evaluate(final Token token) throws NoMatchesFoundException,
+ InvalidRuleException {
+ final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) token.getWorkingMemory();
+ final LeapsRule leapsRule = token.getCurrentRuleHandle().getLeapsRule();
+ // sometimes there is no normal conditions, only not and exists
+ final int numberOfColumns = leapsRule.getNumberOfColumns();
+ // if (numberOfColumns > 0) {
+ final int dominantFactPosition = token.getCurrentRuleHandle().getDominantPosition();
+ final InternalFactHandle dominantFactHandle = token.getDominantFactHandle();
+ if ( leapsRule.getColumnConstraintsAtPosition( dominantFactPosition ).isAllowedAlpha( dominantFactHandle,
+ token,
+ workingMemory ) ) {
+ final Object dominantClass = leapsRule.getColumnClassObjectTypeAtPosition( dominantFactPosition );
+ final TableIterator[] iterators = new TableIterator[numberOfColumns];
+ // getting iterators first
+ for ( int i = 0; i < numberOfColumns; i++ ) {
+ final Object columnClass = leapsRule.getColumnClassObjectTypeAtPosition( i );
+ final ColumnConstraints constraints = leapsRule.getColumnConstraintsAtPosition( i );
+ // we do not need iterators for From constraint
+ if ( constraints.getClass() != FromConstraint.class ) {
+ if ( i == dominantFactPosition ) {
+ iterators[i] = Table.singleItemIterator( dominantFactHandle );
+ } else {
+ final FactTable factTable = workingMemory.getFactTable( columnClass );
+ final LeapsFactHandle startFactHandle = (dominantClass == columnClass) ? new LeapsFactHandle( dominantFactHandle.getRecency() - 1,
+ new Object() ) : (LeapsFactHandle) dominantFactHandle;
+ if ( i > 0 && constraints.isAlphaPresent() ) {
+ iterators[i] = factTable.constrainedIteratorFromPositionToTableStart( workingMemory,
+ constraints,
+ startFactHandle,
+ (token.isResume() ? (LeapsFactHandle) token.get( i ) : startFactHandle) );
+ } else {
+ iterators[i] = factTable.iteratorFromPositionToTableStart( startFactHandle,
+ (token.isResume() ? (LeapsFactHandle) token.get( i ) : startFactHandle) );
+ }
+ }
+ } else {
+ // we do not need iterator for from constraint
+ // it has its own
+ iterators[i] = null;
+ }
+ }
+
+ // check if any iterators are empty to abort
+ // check if we resume and any starting facts disappeared than we
+ // do not do skip on resume
+ boolean doReset = false;
+ boolean skip = token.isResume();
+ TableIterator currentIterator;
+ for ( int i = 0; i < numberOfColumns; i++ ) {
+ currentIterator = iterators[i];
+ if ( currentIterator != null ) {
+ // check if one of them is empty and immediate return
+ if ( currentIterator.isEmpty() ) {
+ throw new NoMatchesFoundException();
+ } else {
+ if ( !doReset ) {
+ if ( skip && currentIterator.hasNext() && !currentIterator.peekNext().equals( token.get( i ) ) ) {
+ // we tried to resume but our fact handle at
+ // marker
+ // disappear no need to resume just reset all
+ // interators
+ // positioned at the marker where we stoped last
+ // time
+ skip = false;
+ doReset = true;
+ }
+ } else {
+ currentIterator.reset();
+ }
+ }
+ }
+ }
+
+ // iterating is done in nested loop
+ // column position in the nested loop
+ int jj = 0;
+ boolean done = false;
+ final int stopIteratingCount = numberOfColumns - 1;
+ while ( !done ) {
+ currentIterator = iterators[jj];
+ // if it's not From and does not have next
+ if ( currentIterator != null && !currentIterator.hasNext() ) {
+ if ( jj == 0 ) {
+ done = true;
+ } else {
+ // nothing for this column, go back and check next
+ // on the one level up in nested loop
+ currentIterator.reset();
+ jj = jj - 1;
+ if ( skip ) {
+ skip = false;
+ }
+ }
+ } else {
+ boolean localMatch = false;
+ LeapsFactHandle currentFactHandle = null;
+ if ( currentIterator != null ) {
+ currentFactHandle = (LeapsFactHandle) currentIterator.next();
+ // check if match found we need to check only beta for
+ // dominant fact
+ // alpha was already checked
+ if ( !skip ) {
+ if ( jj != 0 || jj == dominantFactPosition ) {
+ localMatch = leapsRule.getColumnConstraintsAtPosition( jj ).isAllowedBeta( currentFactHandle,
+ token,
+ workingMemory );
+ } else {
+ localMatch = leapsRule.getColumnConstraintsAtPosition( jj ).isAllowed( currentFactHandle,
+ token,
+ workingMemory );
+ }
+ }
+ } else {
+ final Object fromMatch = TokenEvaluator.evaluateFrom( (FromConstraint) leapsRule.getColumnConstraintsAtPosition( jj ),
+ token,
+ leapsRule,
+ workingMemory );
+ if ( fromMatch != null ) {
+ localMatch = true;
+ // this is not a real fact. just to make it work with
+ // token / tuple
+ currentFactHandle = new LeapsFactHandle( -1,
+ fromMatch );
+ }
+ }
+ if ( localMatch || skip ) {
+ token.set( jj,
+ currentFactHandle );
+ // start iteratating next iterator or for the last
+ // one check negative conditions and fire consequence
+ if ( jj == stopIteratingCount ) {
+ if ( !skip ) {
+ final LeapsTuple tuple = token.getTuple();
+ if ( processAfterAllPositiveConstraintOk( tuple,
+ leapsRule,
+ workingMemory ) ) {
+ workingMemory.assertTuple( tuple );
+ return;
+ }
+ } else {
+ skip = false;
+ }
+ } else {
+ jj = jj + 1;
+ }
+ }
+ }
+ }
+ }
+ // nothing was found. inform caller about it
+ throw new NoMatchesFoundException();
+ }
+
+ /**
+ * Makes final check on eval, exists and not conditions after all column
+ * values isAllowed by column constraints
+ *
+ * @param token
+ * @param leapsRule
+ * @param workingMemory
+ * @return
+ * @throws Exception
+ */
+ final static boolean processAfterAllPositiveConstraintOk(final LeapsTuple tuple,
+ final LeapsRule leapsRule,
+ final LeapsWorkingMemory workingMemory) {
+ if ( leapsRule.containsEvalConditions() && !TokenEvaluator.evaluateEvalConditions( tuple,
+ leapsRule,
+ workingMemory ) ) {
+ return false;
+ }
+ if ( leapsRule.containsExistsColumns() ) {
+ TokenEvaluator.evaluateExistsConditions( tuple,
+ leapsRule,
+ workingMemory );
+ }
+ if ( tuple.isReadyForActivation() && leapsRule.containsNotColumns() ) {
+ TokenEvaluator.evaluateNotConditions( tuple,
+ leapsRule,
+ workingMemory );
+ }
+ //
+ return tuple.isReadyForActivation();
+ }
+
+ /**
+ * checks is EvalConditions isAllowed()
+ *
+ * @param leapsRule
+ * @param tuple
+ * @param workingMemory
+ * @return
+ * @throws Exception
+ */
+ private final static Object evaluateFrom(final FromConstraint from,
+ final Tuple tuple,
+ final LeapsRule leapsRule,
+ final LeapsWorkingMemory workingMemory) {
+ for ( final Iterator it = from.getProvider().getResults( tuple,
+ workingMemory,
+ null ); it.hasNext(); ) {
+ final Object object = it.next();
+ if ( from.isAllowed( new DefaultFactHandle( -1,
+ object ),
+ tuple,
+ workingMemory ) ) {
+ return object;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * checks is EvalConditions isAllowed()
+ *
+ * @param leapsRule
+ * @param tuple
+ * @param workingMemory
+ * @return
+ * @throws Exception
+ */
+ private final static boolean evaluateEvalConditions(final LeapsTuple tuple,
+ final LeapsRule leapsRule,
+ final LeapsWorkingMemory workingMemory) {
+ final EvalCondition[] evals = leapsRule.getEvalConditions();
+ for ( int i = 0; i < evals.length; i++ ) {
+ if ( !evals[i].isAllowed( tuple,
+ workingMemory ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check if any of the negative conditions are satisfied success when none
+ * found
+ *
+ * @param memory
+ * @param token
+ * @return success
+ * @throws Exception
+ */
+ final static void evaluateNotConditions(final LeapsTuple tuple,
+ final LeapsRule rule,
+ final LeapsWorkingMemory workingMemory) {
+ // stops if exists
+ boolean done = false;
+ final ColumnConstraints[] not = rule.getNotColumnConstraints();
+ for ( int i = 0, length = not.length; i < length && !done; i++ ) {
+ final ColumnConstraints constraint = not[i];
+ // scan table starting at start fact handle
+ final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType() ).reverseOrderIterator( tuple,
+ constraint );
+ while ( !done && tableIterator.hasNext() ) {
+ final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next();
+ // check constraint conditions
+ if ( constraint.isAllowed( factHandle,
+ tuple,
+ workingMemory ) ) {
+ tuple.setBlockingNotFactHandle( factHandle,
+ i );
+ factHandle.addNotTuple( tuple,
+ i );
+ done = true;
+ }
+ }
+ }
+ }
+
+ /**
+ * Check if any of the exists conditions are satisfied
+ *
+ * @param tuple
+ * @param memory
+ * @throws Exception
+ */
+ public final static void evaluateExistsConditions(final LeapsTuple tuple,
+ final LeapsRule rule,
+ final LeapsWorkingMemory workingMemory) {
+ // stop if exists
+ boolean notFound = false;
+ boolean done = false;
+ final ColumnConstraints[] exists = rule.getExistsColumnConstraints();
+ for ( int i = 0, length = exists.length; !notFound && i < length; i++ ) {
+ final ColumnConstraints constraint = exists[i];
+ if ( !tuple.isExistsFactHandle( i ) ) {
+ // scan table starting at start fact handle
+ final TableIterator tableIterator = workingMemory.getFactTable( constraint.getClassType() ).reverseOrderIterator( tuple,
+ constraint );
+ done = false;
+ while ( !done && tableIterator.hasNext() ) {
+ final LeapsFactHandle factHandle = (LeapsFactHandle) tableIterator.next();
+ // check constraint conditions
+ if ( constraint.isAllowed( factHandle,
+ tuple,
+ workingMemory ) ) {
+ tuple.setExistsFactHandle( factHandle,
+ i );
+ factHandle.addExistsTuple( tuple,
+ i );
+ done = true;
+ }
+ }
+ if ( !done ) {
+ notFound = true;
+ workingMemory.getFactTable( constraint.getClassType() ).addTuple( tuple );
+ }
+ }
+ }
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/AbstractConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,47 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+
+import org.drools.leaps.ConflictResolver;
+
+/**
+ * A blueprint for conflict resolers
+ *
+ * @author Alexander Bagerman
+ *
+ */
+
+abstract class AbstractConflictResolver
+ implements
+ ConflictResolver {
+ // need for comparator
+ static int compare(final int i1,
+ final int i2) {
+ return i1 - i2;
+ }
+
+ static int compare(final long l1,
+ final long l2) {
+ return (int) (l1 - l2);
+ }
+
+ public abstract Comparator getFactConflictResolver();
+
+ public abstract Comparator getRuleConflictResolver();
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/CompositeConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,91 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * Strategy for resolving conflicts amongst multiple rules.
+ *
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+
+class CompositeConflictResolver extends AbstractConflictResolver {
+ final Comparator[] factResolvers;
+
+ final Comparator[] ruleResolvers;
+
+ public CompositeConflictResolver(final Comparator[] factResolvers,
+ final Comparator[] ruleResolvers) {
+ this.factResolvers = factResolvers;
+ this.ruleResolvers = ruleResolvers;
+ }
+
+ public final Comparator getFactConflictResolver() {
+ return new FactConflictResolver();
+ }
+
+ class FactConflictResolver
+ implements
+ Comparator,
+ Serializable {
+ public int compare(final Object o1,
+ final Object o2) {
+ int ret = 0;
+ if ( o1 != o2 ) {
+ for ( int i = 0, length = CompositeConflictResolver.this.factResolvers.length; ret == 0 && i < length; ++i ) {
+ ret = CompositeConflictResolver.this.factResolvers[i].compare( o1,
+ o2 );
+ }
+ }
+ return ret;
+ }
+ }
+
+ public final Comparator getRuleConflictResolver() {
+ return new RuleConflictResolver();
+ }
+
+ class RuleConflictResolver
+ implements
+ Comparator,
+ Serializable {
+ public int compare(final Object o1,
+ final Object o2) {
+ int ret = 0;
+ if ( o1 != o2 ) {
+ for ( int i = 0, length = CompositeConflictResolver.this.ruleResolvers.length; ret == 0 && i < length; ++i ) {
+ ret = CompositeConflictResolver.this.ruleResolvers[i].compare( o1,
+ o2 );
+ }
+ }
+ return ret;
+ }
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/DefaultConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,63 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+
+import org.drools.leaps.ConflictResolver;
+
+/**
+ * Default strategy for resolving conflicts amongst multiple rules.
+ *
+ * <p>
+ * Since a fact or set of facts may activate multiple rules, a
+ * <code>ConflictResolutionStrategy</code> is used to provide priority
+ * ordering of conflicting rules.
+ * </p>
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+public class DefaultConflictResolver extends CompositeConflictResolver {
+
+ private static final Comparator[] FACT_CONFLICT_RESOLVERS = new Comparator[]{LoadOrderConflictResolver.getInstance()};
+
+ private static final Comparator[] RULE_CONFLICT_RESOLVERS = new Comparator[]{RuleSalienceConflictResolver.getInstance(), RuleComplexityConflictResolver.getInstance(), LoadOrderConflictResolver.getInstance()};
+
+ /** Singleton instance. */
+ private static final DefaultConflictResolver INSTANCE = new DefaultConflictResolver();
+
+ /**
+ * Retrieve the singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ public static ConflictResolver getInstance() {
+ return DefaultConflictResolver.INSTANCE;
+ }
+
+ /**
+ * Setup a default ConflictResolver configuration
+ */
+ public DefaultConflictResolver() {
+ super( DefaultConflictResolver.FACT_CONFLICT_RESOLVERS,
+ DefaultConflictResolver.RULE_CONFLICT_RESOLVERS );
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/LoadOrderConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,66 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.common.DefaultFactHandle;
+
+/**
+ * <code>LoadOrderConflictResolver</code> that uses the load order of rules to
+ * resolve conflict.
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+public class LoadOrderConflictResolver
+ implements
+ Comparator,
+ Serializable {
+
+ /** Singleton instance. */
+ private static final LoadOrderConflictResolver INSTANCE = new LoadOrderConflictResolver();
+
+ /**
+ * Retrieve the singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ public static Comparator getInstance() {
+ return LoadOrderConflictResolver.INSTANCE;
+ }
+
+ /**
+ * Construct.
+ */
+ private LoadOrderConflictResolver() {
+ // intentionally left blank
+ }
+
+ /**
+ * @see LeapsRuleConflictResolver
+ */
+ public int compare(final Object o1,
+ final Object o2) {
+ return (-1) * AbstractConflictResolver.compare( ((DefaultFactHandle) o1).getRecency(),
+ ((DefaultFactHandle) o2).getRecency() );
+ };
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleComplexityConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,65 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the rule complexity.
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleComplexityConflictResolver
+ implements
+ Comparator,
+ Serializable {
+
+ /** Singleton instance. */
+ private static final RuleComplexityConflictResolver INSTANCE = new RuleComplexityConflictResolver();
+
+ /**
+ * Retrieve the singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ public static Comparator getInstance() {
+ return RuleComplexityConflictResolver.INSTANCE;
+ }
+
+ /**
+ * Construct.
+ */
+ private RuleComplexityConflictResolver() {
+ // intentionally left blank
+ }
+
+ /**
+ * @see LeapsRuleConflictResolver
+ */
+ public int compare(final Object o1,
+ final Object o2) {
+ return (-1) * AbstractConflictResolver.compare( (((LeapsRuleHandle) o1).getRuleComplexity()),
+ (((LeapsRuleHandle) o2).getRuleComplexity()) );
+ };
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleLoadOrderConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,69 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the load order of rules to
+ * resolve conflict.
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleLoadOrderConflictResolver
+ implements
+ Comparator {
+
+ /** Singleton instance. */
+ private static final RuleLoadOrderConflictResolver INSTANCE = new RuleLoadOrderConflictResolver();
+
+ /**
+ * Retrieve the singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ public static Comparator getInstance() {
+ return RuleLoadOrderConflictResolver.INSTANCE;
+ }
+
+ /**
+ * Construct.
+ */
+ private RuleLoadOrderConflictResolver() {
+ // intentionally left blank
+ }
+
+ /**
+ * @see LeapsRuleLoadOrderResolver
+ */
+ public int compare(final Object o1,
+ final Object o2) {
+ int ret = LoadOrderConflictResolver.getInstance().compare( o1,
+ o2 );
+ if ( ret == 0 ) {
+ ret = (-1) * AbstractConflictResolver.compare( ((LeapsRuleHandle) o1).getDominantPosition(),
+ ((LeapsRuleHandle) o2).getDominantPosition() );
+ }
+ return ret;
+ };
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/conflict/RuleSalienceConflictResolver.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,65 @@
+package org.drools.leaps.conflict;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import org.drools.leaps.LeapsRuleHandle;
+
+/**
+ * <code>RuleConflictResolver</code> that uses the salience of rules to
+ * resolve conflict.
+ *
+ * @author Alexander Bagerman
+ *
+ * @see org.drools.leaps.conflict.AbstractConflictResolver
+ * @see org.drools.leaps.ConflictResolver
+ * @see org.drools.spi.ConflictResolver
+ */
+class RuleSalienceConflictResolver
+ implements
+ Comparator,
+ Serializable {
+ /** Singleton instance. */
+ private static final RuleSalienceConflictResolver INSTANCE = new RuleSalienceConflictResolver();
+
+ /**
+ * Retrieve the singleton instance.
+ *
+ * @return The singleton instance.
+ */
+ public static Comparator getInstance() {
+ return RuleSalienceConflictResolver.INSTANCE;
+ }
+
+ /**
+ * Construct.
+ */
+ private RuleSalienceConflictResolver() {
+ // intentionally left blank
+ }
+
+ /**
+ * @see LeapsRuleConflictResolver
+ */
+ public int compare(final Object o1,
+ final Object o2) {
+ return (-1) * AbstractConflictResolver.compare( ((LeapsRuleHandle) o1).getSalience(),
+ ((LeapsRuleHandle) o2).getSalience() );
+ };
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/ConstrainedIteratorFromPositionToTableStart.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,111 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.drools.WorkingMemory;
+import org.drools.common.InternalFactHandle;
+import org.drools.leaps.ColumnConstraints;
+
+/**
+ * this class is for multi pass iterations to sort out facts that do not satisfy
+ * alpha nodes
+ *
+ * previous to the left
+ * next to the right
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class ConstrainedIteratorFromPositionToTableStart extends IteratorFromPositionToTableStart {
+ private boolean finishInitialPass = false;
+
+ final WorkingMemory workingMemory;
+
+ final ColumnConstraints constraints;
+
+ private TableRecord currentTableRecord;
+
+ protected ConstrainedIteratorFromPositionToTableStart(final WorkingMemory workingMemory,
+ final ColumnConstraints constraints,
+ final TableRecord startRecord,
+ final TableRecord currentRecord) {
+ super( null );
+ this.workingMemory = workingMemory;
+ this.constraints = constraints;
+ this.currentTableRecord = startRecord;
+ boolean done = false;
+ boolean reachCurrentRecord = false;
+ while ( !done && this.currentTableRecord != null && !this.finishInitialPass ) {
+ if ( !reachCurrentRecord && this.currentTableRecord == currentRecord ) {
+ reachCurrentRecord = true;
+ } else {
+ if ( this.constraints.isAllowedAlpha( (InternalFactHandle) this.currentTableRecord.object,
+ null,
+ this.workingMemory ) ) {
+ this.add( this.currentTableRecord.object );
+ }
+ if ( reachCurrentRecord && !this.isEmpty() ) {
+ done = true;
+ }
+ if ( this.currentTableRecord.right == null ) {
+ this.finishInitialPass = true;
+ }
+ this.currentTableRecord = this.currentTableRecord.right;
+ }
+ }
+ }
+
+ private void add(final Object object) {
+ final TableRecord record = new TableRecord( object );
+ if ( this.firstRecord == null ) {
+ this.firstRecord = record;
+ this.currentRecord = record;
+ } else {
+ this.currentRecord.right = record;
+ record.left = this.currentRecord;
+ this.currentRecord = record;
+ }
+
+ this.nextRecord = this.currentRecord;
+ }
+
+ public boolean hasNext() {
+ if ( !this.finishInitialPass ) {
+ if ( this.nextRecord == null ) {
+ boolean found = false;
+ while ( !found && this.currentTableRecord != null ) {
+ if ( this.constraints.isAllowedAlpha( (InternalFactHandle) this.currentTableRecord.object,
+ null,
+ this.workingMemory ) ) {
+ this.add( this.currentTableRecord.object );
+ found = true;
+ }
+ if ( this.currentTableRecord == null ) {
+ this.finishInitialPass = true;
+ }
+ this.currentTableRecord = this.currentTableRecord.right;
+ }
+
+ return found;
+ } else {
+ return true;
+ }
+ } else {
+ return super.hasNext();
+ }
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableEnd.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,63 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.NoSuchElementException;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigation
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class IteratorFromPositionToTableEnd extends IteratorFromPositionToTableStart {
+ /**
+ * @see IteratorFromPositionToTableStart
+ */
+ protected IteratorFromPositionToTableEnd(final TableRecord record) {
+ super( record );
+ }
+
+ /**
+ * @see IteratorFromPositionToTableStart
+ */
+ protected IteratorFromPositionToTableEnd(final TableRecord startRecord,
+ final TableRecord currentRecord) {
+ super( startRecord,
+ currentRecord );
+ }
+
+ /**
+ * the difference here is that we are going to the different direction that
+ * base class next() method
+ *
+ * @see IteratorFromPositionToTableStart
+ *
+ */
+
+ public Object next() {
+ this.currentRecord = this.nextRecord;
+ if ( this.currentRecord != null ) {
+ this.nextRecord = this.currentRecord.left;
+ } else {
+ throw new NoSuchElementException( "No more elements to return" );
+ }
+ return this.currentRecord.object;
+ }
+
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/IteratorFromPositionToTableStart.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,91 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.NoSuchElementException;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigation
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class IteratorFromPositionToTableStart
+ implements
+ TableIterator {
+ /**
+ * interator that was not initialized as "empty" iterator (one or another
+ * record was submitted to constractor) will set it to false
+ */
+ TableRecord firstRecord;
+
+ TableRecord currentRecord;
+
+ TableRecord nextRecord;
+
+ /**
+ * constracts an leaps iterator to iterate over a single record. Used for
+ * Dominant fact dimention iteration
+ *
+ * @param record
+ * to iterate over
+ */
+
+ protected IteratorFromPositionToTableStart(final TableRecord record) {
+ this.firstRecord = record;
+ this.currentRecord = null;
+ this.nextRecord = this.firstRecord;
+ }
+
+ public IteratorFromPositionToTableStart(final TableRecord startRecord,
+ final TableRecord currentRecord) {
+ this.firstRecord = startRecord;
+ this.nextRecord = currentRecord;
+ this.currentRecord = null;
+ }
+
+ public boolean isEmpty() {
+ return this.firstRecord == null;
+ }
+
+ public void reset() {
+ this.currentRecord = null;
+ this.nextRecord = this.firstRecord;
+ }
+
+ public boolean hasNext() {
+ return this.nextRecord != null;
+ }
+
+ public Object next() {
+ this.currentRecord = this.nextRecord;
+ if ( this.currentRecord != null ) {
+ this.nextRecord = this.currentRecord.right;
+ } else {
+ throw new NoSuchElementException( "No more elements to return" );
+ }
+ return this.currentRecord.object;
+ }
+
+ public Object peekNext() {
+ return this.nextRecord.object;
+ }
+
+ public void remove() {
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/RecordComparator.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,46 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * this class wraps object comparator to sort records holding given objects in
+ * a list
+ *
+ * @author Alexander Bagerman
+ *
+ */
+
+class RecordComparator
+ implements
+ Comparator,
+ Serializable {
+ private Comparator objectComparator;
+
+ RecordComparator(final Comparator objectComparator) {
+ this.objectComparator = objectComparator;
+ }
+
+ public int compare(final Object record1,
+ final Object record2) {
+ return this.objectComparator.compare( ((TableRecord) record1).object,
+ ((TableRecord) record2).object );
+ }
+
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/Table.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,344 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.TreeSet;
+
+import org.drools.WorkingMemory;
+import org.drools.leaps.ColumnConstraints;
+
+/**
+ * double linked list structure to store objects in the ordered list
+ * and iterate over the list for leaps
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class Table
+ implements
+ Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2614082619270512055L;
+
+ private final TreeSet set;
+
+ protected TableRecord headRecord;
+
+ protected TableRecord tailRecord;
+
+ private boolean empty = true;
+
+ private int count = 0;
+
+ public Table(final Comparator comparator) {
+ this.set = new TreeSet( new RecordComparator( comparator ) );
+ }
+
+ public void clear() {
+ this.headRecord = null;
+ this.empty = true;
+ this.count = 0;
+ this.set.clear();
+ }
+
+ /**
+ * @param object
+ * to add
+ */
+ public void add(final Object object) {
+ final TableRecord newRecord = new TableRecord( object );
+ if ( this.empty ) {
+ this.headRecord = newRecord;
+ this.empty = false;
+ } else {
+ try {
+ // check on first key should work faster than check on empty
+ // but logically we check on empty
+ // if map empty it will throw exception
+ final TableRecord bufRec = (TableRecord) this.set.headSet( newRecord ).last();
+ if ( bufRec.right != null ) {
+ bufRec.right.left = newRecord;
+ }
+ newRecord.right = bufRec.right;
+ bufRec.right = newRecord;
+ newRecord.left = bufRec;
+
+ } catch ( final NoSuchElementException nsee ) {
+ // means sub map is empty
+ this.headRecord.left = newRecord;
+ newRecord.right = this.headRecord;
+ this.headRecord = newRecord;
+ }
+ }
+ // check if the new record was added at the end of the list
+ // and assign new value to the tail record
+ if ( newRecord.right == null ) {
+ this.tailRecord = newRecord;
+ }
+ //
+ this.count++;
+ //
+ this.set.add( newRecord );
+ }
+
+ /**
+ * Removes object from the table
+ *
+ * @param object
+ * to remove from the table
+ */
+ public void remove(final Object object) {
+ if ( !this.empty ) {
+ try {
+ final TableRecord record = (TableRecord) this.set.tailSet( new TableRecord( object ) ).first();
+ if ( record != null && record.object == object ) {
+ if ( record == this.headRecord ) {
+ if ( record.right != null ) {
+ this.headRecord = record.right;
+ this.headRecord.left = null;
+ } else {
+ // single element in table being valid
+ // table is empty now
+ this.headRecord = null;
+ this.tailRecord = null;
+ this.empty = true;
+ }
+ } else if ( record == this.tailRecord ) {
+ // single element in the table case is being solved
+ // above in check for headRecord match
+ this.tailRecord = record.left;
+ this.tailRecord.right = null;
+ } else {
+ // left
+ record.left.right = record.right;
+ record.right.left = record.left;
+ }
+ record.left = null;
+ record.right = null;
+ } else {
+ throw new NoSuchElementException();
+ }
+ this.count--;
+ //
+ this.set.remove( record );
+ } catch ( final NoSuchElementException nsee ) {
+ throw nsee;
+ }
+ }
+ }
+
+ /**
+ * @param object
+ * @return indicator of presence of given object in the table
+ */
+ public boolean contains(final Object object) {
+ boolean ret = false;
+ if ( !this.empty ) {
+ ret = this.set.contains( new TableRecord( object ) );
+ }
+ return ret;
+ }
+
+ /**
+ * @return TableIterator for this Table
+ * @see org.drools.leaps.util.TableIterator
+ * @see org.drools.leaps.util.IteratorFromPositionToTableStart
+ */
+ public TableIterator iterator() {
+ TableIterator ret;
+ if ( this.empty ) {
+ ret = new IteratorFromPositionToTableStart( null,
+ null );
+ } else {
+ ret = new IteratorFromPositionToTableStart( this.headRecord,
+ this.headRecord );
+ }
+ return ret;
+ }
+
+ public TableIterator reverseOrderIterator() {
+ TableIterator ret;
+ if ( this.empty ) {
+ ret = new IteratorFromPositionToTableEnd( null,
+ null );
+ } else {
+ ret = new IteratorFromPositionToTableEnd( this.tailRecord,
+ this.tailRecord );
+ }
+ return ret;
+ }
+
+ /**
+ * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+ * iterator at objectAtPosition for resumed iterations
+ *
+ * @param objectAtStart -
+ * upper boundary of the iteration
+ * @param objectAtPosition -
+ * starting point of the iteration
+ * @return leaps table iterator
+ * @throws TableOutOfBoundException
+ */
+ public TableIterator constrainedIteratorFromPositionToTableStart(final WorkingMemory workingMemory,
+ final ColumnConstraints constraints,
+ final Object objectAtStart,
+ final Object objectAtPosition) {
+ return getIteratorFromPositionToTableStart( true,
+ workingMemory,
+ constraints,
+ objectAtStart,
+ objectAtPosition );
+ }
+
+ /**
+ * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+ * iterator at objectAtPosition for resumed iterations
+ *
+ * @param objectAtStart -
+ * upper boundary of the iteration
+ * @param objectAtPosition -
+ * starting point of the iteration
+ * @return leaps table iterator
+ * @throws TableOutOfBoundException
+ */
+ public TableIterator iteratorFromPositionToTableStart(final Object objectAtStart,
+ final Object objectAtPosition) {
+ return getIteratorFromPositionToTableStart( false,
+ null,
+ null,
+ objectAtStart,
+ objectAtPosition );
+ }
+
+ /**
+ * retrieve iterator over portion of the table data starting at objectAtStart and positioning
+ * iterator at objectAtPosition for resumed iterations
+ *
+ * @param objectAtStart -
+ * upper boundary of the iteration
+ * @param objectAtPosition -
+ * starting point of the iteration
+ * @return leaps table iterator
+ * @throws TableOutOfBoundException
+ */
+ public TableIterator iteratorFromPositionToTableEnd(final Object objectAtStart) {
+ TableRecord record = null;
+ try {
+ record = (TableRecord) this.set.headSet( new TableRecord( objectAtStart ) ).last();
+ } catch ( final NoSuchElementException nsee ) {
+ }
+
+ return new IteratorFromPositionToTableEnd( record,
+ record );
+ }
+
+ /**
+ * retrieve Markers structure for a given objectAtStart.
+ *
+ * @param objectAtStart -
+ * upper boundary of the iteration
+ * @return Markers structure
+ */
+ private TableIterator getIteratorFromPositionToTableStart(final boolean isConstraint,
+ final WorkingMemory workingMemory,
+ final ColumnConstraints constraints,
+ final Object objectAtStart,
+ final Object objectAtPosition) {
+ TableRecord startRecord = null;
+ TableRecord currentRecord = null;
+
+ final TableRecord recordAtStart = new TableRecord( objectAtStart );
+ if ( !this.empty ) {
+ try {
+ // check on first key should work faster than check
+ // to see if set has no elements
+ // if set is empty it will throw exception
+ startRecord = (TableRecord) this.set.tailSet( recordAtStart ).first();
+ if ( objectAtStart == objectAtPosition ) {
+ currentRecord = startRecord;
+ } else {
+ // rewind to position
+ try {
+ // check on first key should work faster than check
+ // to see if set has no elements
+ // if set is empty it will throw exception
+ currentRecord = (TableRecord) this.set.tailSet( new TableRecord( objectAtPosition ) ).first();
+ } catch ( final NoSuchElementException nsee ) {
+ currentRecord = startRecord;
+ }
+ }
+ } catch ( final NoSuchElementException nsee ) {
+ }
+ }
+
+ if ( isConstraint ) {
+ return new ConstrainedIteratorFromPositionToTableStart( workingMemory,
+ constraints,
+ startRecord,
+ currentRecord );
+ } else {
+ return new IteratorFromPositionToTableStart( startRecord,
+ currentRecord );
+ }
+ }
+
+ /**
+ * indicates if table has any elements
+ *
+ * @return empty indicator
+ */
+ public boolean isEmpty() {
+ return this.empty;
+ }
+
+ public String toString() {
+ String ret = "";
+
+ for ( final Iterator it = this.iterator(); it.hasNext(); ) {
+ ret = ret + it.next() + "\n";
+ }
+ return ret;
+ }
+
+ public int size() {
+ return this.count;
+ }
+
+ public Object top() {
+ return this.headRecord.object;
+ }
+
+ public Object bottom() {
+ return this.tailRecord.object;
+ }
+
+ public static TableIterator singleItemIterator(final Object object) {
+ return new IteratorFromPositionToTableStart( new TableRecord( object ) );
+ }
+
+ public static TableIterator emptyIterator() {
+ return new IteratorFromPositionToTableStart( null,
+ null );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableIterator.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,47 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+/**
+ * Leaps specific iterator for leaps tables. relies on leaps table double link
+ * list structure for navigating
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public interface TableIterator
+ extends
+ Iterator {
+ /**
+ * single object iterator
+ *
+ * @return table iterator
+ */
+ public boolean isEmpty();
+
+ public void reset();
+
+ public boolean hasNext();
+
+ public Object next();
+
+ public Object peekNext();
+
+ public void remove();
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TableRecord.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,60 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class TableRecord
+ implements
+ Serializable {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 2894253746310217052L;
+
+ // left neigbor
+ TableRecord left;
+
+ // right neigbor
+ TableRecord right;
+
+ // content of the record
+ Object object;
+
+ TableRecord(final Object o) {
+ this.left = null;
+ this.right = null;
+ this.object = o;
+ }
+
+ public int hashCode() {
+ return this.object.hashCode();
+ }
+
+ public boolean equals(final Object that) {
+ if ( this.object != null ) {
+ return this.object.equals( ((TableRecord) that).object );
+ } else {
+ return that == null;
+ }
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/main/java/org/drools/leaps/util/TokenStack.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,131 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.Serializable;
+import java.util.EmptyStackException;
+import java.util.Iterator;
+
+import org.drools.leaps.Token;
+import org.drools.util.PrimitiveLongMap;
+
+/**
+ * This class follows java.util.Stack interface but accounts for remove( object )
+ * functionallity needed by leaps
+ *
+ * @author Alexander Bagerman
+ *
+ */
+
+public class TokenStack
+ implements
+ Serializable {
+
+ protected TableRecord tailRecord = null;
+
+ private final PrimitiveLongMap map = new PrimitiveLongMap();
+
+ public TokenStack() {
+
+ }
+
+ public boolean empty() {
+ return this.tailRecord == null;
+ }
+
+ public Object peek() {
+ if ( this.tailRecord != null ) {
+ return this.tailRecord.object;
+ } else {
+ throw new EmptyStackException();
+ }
+ }
+
+ public Object pop() {
+ if ( this.tailRecord != null ) {
+ final Object ret = this.tailRecord.object;
+ final TableRecord buf = this.tailRecord;
+ this.tailRecord = buf.left;
+ if ( buf.left != null ) {
+ this.tailRecord.right = null;
+ }
+ buf.left = null;
+
+ this.map.remove( ((Token) ret).getDominantFactHandle().getId() );
+ return ret;
+ } else {
+ throw new EmptyStackException();
+ }
+ }
+
+ /**
+ * Removes object from the table
+ *
+ * @param object
+ * to remove from the table
+ */
+ public void remove(final long factId) {
+ if ( this.tailRecord != null ) {
+ final TableRecord record = (TableRecord) this.map.remove( factId );
+
+ if ( record != null ) {
+ if ( record == this.tailRecord ) {
+ this.tailRecord = record.left;
+ }
+ if ( record.left != null ) {
+ record.left.right = record.right;
+ }
+ if ( record.right != null ) {
+ record.right.left = record.left;
+ }
+ record.left = null;
+ record.right = null;
+ }
+ }
+ }
+
+ public Object push(final Object item) {
+ final TableRecord record = new TableRecord( item );
+ if ( this.tailRecord != null ) {
+ this.tailRecord.right = record;
+ record.left = this.tailRecord;
+ }
+ this.tailRecord = record;
+
+ this.map.put( ((Token) item).getDominantFactHandle().getId(),
+ record );
+ return item;
+ }
+
+ public Iterator iterator() {
+ return new Iterator() {
+ Iterator it = TokenStack.this.map.values().iterator();
+
+ public boolean hasNext() {
+ return this.it.hasNext();
+ }
+
+ public void remove() {
+
+ }
+
+ public Object next() {
+ return this.it.next();
+ }
+ };
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/ColumnConstraintsTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,164 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.LiteralConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.MockField;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class ColumnConstraintsTest extends DroolsTestCase {
+
+ Evaluator integerEqualEvaluator;
+
+ Evaluator integerNotEqualEvaluator;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+ this.integerNotEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.NOT_EQUAL );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testEvaluateAlphasSuccess() throws Exception {
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ final ArrayList alphas = new ArrayList();
+ ColumnConstraints columnConstraints;
+ AlphaNodeFieldConstraint constraint;
+ final ClassObjectType contextType = new ClassObjectType( Context.class );
+ final Column testColumn = new Column( 0,
+ contextType,
+ "state" );
+
+ constraint = getLiteralConstraint( testColumn,
+ "state",
+ new Integer( Context.START_UP ),
+ this.integerEqualEvaluator );
+ alphas.add( constraint );
+ testColumn.addConstraint( constraint );
+ constraint = getLiteralConstraint( testColumn,
+ "state",
+ new Integer( -999999 ),
+ this.integerNotEqualEvaluator );
+ alphas.add( constraint );
+ testColumn.addConstraint( constraint );
+
+ columnConstraints = new ColumnConstraints( testColumn,
+ alphas,
+ null );
+
+ final LeapsTuple tuple = new LeapsTuple( new LeapsFactHandle[0],
+ null,
+ null );
+ assertTrue( columnConstraints.isAllowed( new LeapsFactHandle( 23,
+ new Context( Context.START_UP ) ),
+ tuple,
+ ruleBase.newWorkingMemory() ) );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testEvaluateAlphasFalure() throws Exception {
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ final ArrayList alphas = new ArrayList();
+ ColumnConstraints columnConstraints;
+ AlphaNodeFieldConstraint constraint;
+ final ClassObjectType contextType = new ClassObjectType( Context.class );
+ final Column testColumn = new Column( 0,
+ contextType,
+ "state" );
+
+ constraint = getLiteralConstraint( testColumn,
+ "state",
+ new Integer( Context.START_UP ),
+ this.integerEqualEvaluator );
+ alphas.add( constraint );
+ testColumn.addConstraint( constraint );
+ constraint = getLiteralConstraint( testColumn,
+ "state",
+ new Integer( -999999 ),
+ this.integerEqualEvaluator );
+ alphas.add( constraint );
+ testColumn.addConstraint( constraint );
+
+ columnConstraints = new ColumnConstraints( testColumn,
+ alphas,
+ null );
+
+ assertFalse( columnConstraints.isAllowed( new LeapsFactHandle( 23,
+ new Context( Context.START_UP ) ),
+ null,
+ ruleBase.newWorkingMemory() ) );
+
+ }
+
+ private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator) throws IntrospectionException {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldValue field = new MockField( fieldValue );
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ return new LiteralConstraint( extractor,
+ evaluator,
+ field );
+ }
+
+ public static int getIndex(final Class clazz,
+ final String name) throws IntrospectionException {
+ final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+ for ( int i = 0; i < descriptors.length; i++ ) {
+ if ( descriptors[i].getName().equals( name ) ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/CrossProductTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,94 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassObjectType;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.ObjectType;
+
+public class CrossProductTest extends TestCase {
+ public void test1() throws Exception {
+ final ObjectType list1ObjectType = new ClassObjectType( List.class );
+ final ObjectType list2ObjectType = new ClassObjectType( List.class );
+
+ final Rule rule = new Rule( "rule-1" );
+
+ final Column list1Column = new Column( 0,
+ list1ObjectType,
+ "list1" );
+ final Column list2Column = new Column( 1,
+ list2ObjectType,
+ "list2" );
+
+ rule.addPattern( list1Column );
+ rule.addPattern( list2Column );
+
+ final Declaration list1Declaration = rule.getDeclaration( "list1" );
+ final Declaration list2Declaration = rule.getDeclaration( "list2" );
+
+ final List values = new ArrayList();
+
+ rule.setConsequence( new Consequence() {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -958666414598812063L;
+
+ public void evaluate(final KnowledgeHelper knowledgeHelper,
+ final WorkingMemory workingMemory) throws Exception {
+ final List list1 = (List) knowledgeHelper.get( list1Declaration );
+ final List list2 = (List) knowledgeHelper.get( list2Declaration );
+ values.add( new List[]{list1, list2} );
+ }
+
+ } );
+
+ final Package pkg = new Package( "org.drools" );
+ pkg.addRule( rule );
+
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ ruleBase.addPackage( pkg );
+
+ final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+ workingMemory.assertObject( new ArrayList() );
+ workingMemory.assertObject( new ArrayList() );
+ workingMemory.assertObject( new LinkedList() );
+ workingMemory.assertObject( new LinkedList() );
+
+ workingMemory.fireAllRules();
+
+ // A full cross product is 16, this is just 12
+ assertEquals( 12,
+ values.size() );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/FactHandleImplTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,61 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class FactHandleImplTest extends TestCase {
+
+ private LeapsRuleBase ruleBase;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ }
+
+ /*
+ * Test method for 'leaps.LeapsFactHandle.getId()'
+ */
+ public void testGetId() {
+ final LeapsWorkingMemory memory = (LeapsWorkingMemory) this.ruleBase.newWorkingMemory();
+
+ try {
+ final FactHandle fh1 = memory.assertObject( "object1" );
+ assertEquals( ((LeapsFactHandle) fh1).getId(),
+ ((LeapsFactHandle) memory.getFactHandleFactory().newFactHandle( "dummy" )).getId() - 1 );
+ } catch ( final FactException fe ) {
+ }
+ }
+
+ /*
+ * Test method for 'leaps.LeapsFactHandle.equals(Object)'
+ */
+ public void testEqualsObject() {
+ // they equal on id, am not sure how to simulate it yet
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleFactoryTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,98 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class HandleFactoryTest extends TestCase {
+
+ LeapsFactHandleFactory factory;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.factory = new LeapsFactHandleFactory();
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.Handlethis.factory.newFactHandle()'
+ */
+ public void testNewFactHandle() {
+ final Object object = new Object();
+ assertTrue( ((DefaultFactHandle) this.factory.newFactHandle( object )).getObject() == object );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.Handlethis.factory.getNextId()'
+ */
+ public void testGetNextId() {
+ this.factory.getNextId();
+ this.factory.getNextId();
+ this.factory.getNextId();
+ this.factory.getNextId();
+
+ final long nextId = this.factory.getNextId() + 1;
+ assertEquals( nextId,
+ this.factory.getNextId() );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.Handlethis.factory.newFactHandle(Object)'
+ */
+ public void testNewFactHandleObject() {
+ this.factory.getNextId();
+ this.factory.getNextId();
+
+ final String testObject = new String( "test object" );
+ final long nextId = this.factory.getNextId() + 1;
+ final DefaultFactHandle handle = (DefaultFactHandle) this.factory.newFactHandle( testObject );
+ assertEquals( nextId,
+ handle.getId() );
+ assertEquals( testObject,
+ handle.getObject() );
+
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.Handlethis.factory.newFactHandle(long)'
+ */
+ public void testNewFactHandleLong() {
+ this.factory.getNextId();
+ this.factory.getNextId();
+
+ final long nextId = this.factory.getNextId() + 1;
+ assertEquals( nextId,
+ ((DefaultFactHandle) this.factory.newFactHandle( 984393L,
+ new Object() )).getId() );
+
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.Handlethis.factory.newInstance()'
+ */
+ public void testNewInstance() {
+ assertFalse( this.factory == this.factory.newInstance() );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HandleTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class HandleTest extends TestCase {
+
+ /*
+ * Test method for 'leaps.LeapsFactHandle.getId()'
+ */
+ public void testGetId() {
+ final LeapsFactHandle handle = new LeapsFactHandle( 123456789,
+ new String( "test124" ) );
+ assertEquals( handle.getId(),
+ 123456789 );
+ assertEquals( handle.getObject(),
+ "test124" );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/HashedTableComponentTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,418 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.util.Iterator;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.examples.manners.Path;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.InvalidRuleException;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Not;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.MockField;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class HashedTableComponentTest extends DroolsTestCase {
+
+ protected Package pkg;
+
+ private ClassObjectType pathType;
+
+ private Evaluator objectEqualEvaluator;
+
+ private Evaluator integerEqualEvaluator;
+
+ private Path p1Alex;
+
+ private Path p2John;
+
+ private Path p3Mike;
+
+ private Path p4Alex;
+
+ private Path p5Alex;
+
+ protected void setUp() throws Exception {
+
+ this.p1Alex = new Path( 1,
+ 1,
+ "Alex" );
+ this.p2John = new Path( 2,
+ 1,
+ "John" );
+ this.p3Mike = new Path( 3,
+ 1,
+ "Mike" );
+ this.p4Alex = new Path( 4,
+ 1,
+ "Alex" );
+ this.p5Alex = new Path( 1,
+ 4,
+ "Alex" );
+ this.pathType = new ClassObjectType( Path.class );
+
+ this.integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+ this.objectEqualEvaluator = ValueType.OBJECT_TYPE.getEvaluator( Operator.EQUAL );
+
+ this.pkg = new Package( "Miss Manners for Hashed Table Component" );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testHashedTableComponentNoAlpha() throws Exception {
+
+ final Rule r = this.getMakePathNoAlpha();
+ this.pkg.addRule( r );
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ ruleBase.addPackage( this.pkg );
+ final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+ wm.assertObject( this.p1Alex );
+ wm.assertObject( this.p2John );
+ wm.assertObject( this.p3Mike );
+ wm.assertObject( this.p4Alex );
+ wm.assertObject( this.p5Alex );
+
+ Iterator it;
+ Tuple tuple;
+ final FactTable ft = wm.getFactTable( Path.class );
+ final ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints().next();
+ final LeapsFactHandle[] fh = new LeapsFactHandle[1];
+ fh[0] = new LeapsFactHandle( 99,
+ this.p1Alex );
+ tuple = new LeapsTuple( fh,
+ null,
+ null );
+
+ it = ft.reverseOrderIterator( tuple,
+ notConstraint );
+ assertSame( "Expected matching",
+ ((LeapsFactHandle) it.next()).getObject(),
+ this.p1Alex );
+ assertSame( "Expected matching",
+ ((LeapsFactHandle) it.next()).getObject(),
+ this.p5Alex );
+ assertFalse( "Did not expect any more data",
+ it.hasNext() );
+
+ fh[0] = new LeapsFactHandle( 99,
+ this.p3Mike );
+ tuple = new LeapsTuple( fh,
+ null,
+ null );
+
+ it = ft.reverseOrderIterator( tuple,
+ notConstraint );
+ assertSame( "Expected matching",
+ ((LeapsFactHandle) it.next()).getObject(),
+ this.p3Mike );
+ assertFalse( "Did not expect any more data",
+ it.hasNext() );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools.leaps.ColumnConstraints.evaluateAlphas(FactHandleImpl, Token,
+ * WorkingMemoryImpl)'
+ */
+ public void testHashedTableComponentAlpha() throws Exception {
+
+ final Rule r = this.getMakePathAlpha();
+ this.pkg.addRule( r );
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ ruleBase.addPackage( this.pkg );
+ final LeapsWorkingMemory wm = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+
+ wm.assertObject( this.p1Alex );
+ wm.assertObject( this.p2John );
+ wm.assertObject( this.p3Mike );
+ wm.assertObject( this.p4Alex );
+ wm.assertObject( this.p5Alex );
+
+ Iterator it;
+ Tuple tuple;
+ final FactTable ft = wm.getFactTable( Path.class );
+ final ColumnConstraints notConstraint = (ColumnConstraints) ft.getHashedConstraints().next();
+ final LeapsFactHandle[] fh = new LeapsFactHandle[1];
+ fh[0] = new LeapsFactHandle( 99,
+ this.p1Alex );
+ tuple = new LeapsTuple( fh,
+ null,
+ null );
+
+ it = ft.reverseOrderIterator( tuple,
+ notConstraint );
+ assertFalse( "Did not expect any more data",
+ it.hasNext() );
+
+ fh[0] = new LeapsFactHandle( 99,
+ this.p3Mike );
+ tuple = new LeapsTuple( fh,
+ null,
+ null );
+
+ it = ft.reverseOrderIterator( tuple,
+ notConstraint );
+ assertSame( "Expected matching",
+ ((LeapsFactHandle) it.next()).getObject(),
+ this.p3Mike );
+ assertFalse( "Did not expect any more data",
+ it.hasNext() );
+ }
+
+ /**
+ * <pre>
+ * rule makePath() {
+ * int pathId;
+ * String pathGuestName;
+ *
+ * when {
+ * Path( pathId:id, pathGuestName:guest )
+ * (not Path( id == pathId, guestName == pathGuestName )
+ * } then {
+ * nothing;
+ *
+ * }
+ * }
+ * </pre>
+ *
+ * @return
+ * @throws IntrospectionException
+ * @throws InvalidRuleException
+ */
+ private Rule getMakePathAlpha() throws IntrospectionException,
+ InvalidRuleException {
+ final Rule rule = new Rule( "makePathNoAlpha" );
+ // -----------
+ // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+ // -----------
+ final Column pathColumn = new Column( 0,
+ this.pathType );
+ setFieldDeclaration( pathColumn,
+ "id",
+ "pathId" );
+
+ setFieldDeclaration( pathColumn,
+ "guestName",
+ "pathGuestName" );
+
+ rule.addPattern( pathColumn );
+
+ final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+ final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+ // -------------
+ // (not Path( id == seatingId, guestName == pathGuestName )
+ // -------------
+ final Column notPathColumn = new Column( 3,
+ this.pathType );
+
+ notPathColumn.addConstraint( getLiteralConstraint( notPathColumn,
+ "guestName",
+ "Mike",
+ this.objectEqualEvaluator ) );
+
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "id",
+ pathIdDeclaration,
+ this.integerEqualEvaluator ) );
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "guestName",
+ pathGuestNameDeclaration,
+ this.objectEqualEvaluator ) );
+
+ final Not not = new Not();
+
+ not.addChild( notPathColumn );
+
+ rule.addPattern( not );
+
+ // ------------
+ // drools.assert( new Path( id, pathName, pathSeat ) );
+ // ------------
+ final Consequence consequence = new Consequence() {
+
+ public void evaluate(KnowledgeHelper drools,
+ WorkingMemory workingMemory) throws ConsequenceException {
+ // empty
+ }
+ };
+
+ rule.setConsequence( consequence );
+
+ return rule;
+ }
+
+ /**
+ * <pre>
+ * rule makePath() {
+ * int pathId;
+ * String pathGuestName;
+ *
+ * when {
+ * Path( pathId:id, pathGuestName:guest )
+ * (not Path( id == pathId, guestName == pathGuestName )
+ * } then {
+ * nothing;
+ *
+ * }
+ * }
+ * </pre>
+ *
+ * @return
+ * @throws IntrospectionException
+ * @throws InvalidRuleException
+ */
+ private Rule getMakePathNoAlpha() throws IntrospectionException,
+ InvalidRuleException {
+ final Rule rule = new Rule( "makePathNoAlpha" );
+ // -----------
+ // Path( id == seatingPid, pathGuestName:guestName, pathSeat:seat )
+ // -----------
+ final Column pathColumn = new Column( 0,
+ this.pathType );
+ setFieldDeclaration( pathColumn,
+ "id",
+ "pathId" );
+
+ setFieldDeclaration( pathColumn,
+ "guestName",
+ "pathGuestName" );
+
+ rule.addPattern( pathColumn );
+
+ final Declaration pathIdDeclaration = rule.getDeclaration( "pathId" );
+ final Declaration pathGuestNameDeclaration = rule.getDeclaration( "pathGuestName" );
+ // -------------
+ // (not Path( id == seatingId, guestName == pathGuestName )
+ // -------------
+ final Column notPathColumn = new Column( 3,
+ this.pathType );
+
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "id",
+ pathIdDeclaration,
+ this.integerEqualEvaluator ) );
+ notPathColumn.addConstraint( getBoundVariableConstraint( notPathColumn,
+ "guestName",
+ pathGuestNameDeclaration,
+ this.objectEqualEvaluator ) );
+
+ final Not not = new Not();
+
+ not.addChild( notPathColumn );
+
+ rule.addPattern( not );
+
+ // ------------
+ // drools.assert( new Path( id, pathName, pathSeat ) );
+ // ------------
+ final Consequence consequence = new Consequence() {
+
+ public void evaluate(KnowledgeHelper drools,
+ WorkingMemory workingMemory) throws ConsequenceException {
+ // empty
+ }
+ };
+
+ rule.setConsequence( consequence );
+
+ return rule;
+ }
+
+ public static int getIndex(final Class clazz,
+ final String name) throws IntrospectionException {
+ final PropertyDescriptor[] descriptors = Introspector.getBeanInfo( clazz ).getPropertyDescriptors();
+ for ( int i = 0; i < descriptors.length; i++ ) {
+ if ( descriptors[i].getName().equals( name ) ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator) throws IntrospectionException {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ final FieldValue field = new MockField( fieldValue );
+
+ return new LiteralConstraint( extractor,
+ evaluator,
+ field );
+ }
+
+ private void setFieldDeclaration(final Column column,
+ final String fieldName,
+ final String identifier) throws IntrospectionException {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ column.addDeclaration( identifier,
+ extractor );
+ }
+
+ private AlphaNodeFieldConstraint getBoundVariableConstraint(final Column column,
+ final String fieldName,
+ final Declaration declaration,
+ final Evaluator evaluator) throws IntrospectionException {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ return new VariableConstraint( extractor,
+ declaration,
+ evaluator );
+ }
+
+}
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsFactHandleTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,40 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsFactHandleTest extends TestCase {
+
+ /*
+ * Test method for 'leaps.LeapsFactHandle.getId()'
+ */
+ public void testGetId() {
+ final LeapsFactHandle handle = new LeapsFactHandle( 123456789,
+ new String( "test124" ) );
+ assertEquals( handle.getId(),
+ 123456789 );
+ assertEquals( handle.getObject(),
+ "test124" );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsRuleBaseTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,400 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.MockField;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class LeapsRuleBaseTest extends DroolsTestCase {
+ LeapsRuleBase ruleBase;
+ LeapsRuleBase ruleBaseAddRule;
+
+ WorkingMemory wm1;
+
+ WorkingMemory wm2;
+
+ WorkingMemory wm3;
+
+ WorkingMemory wm4;
+
+ // leaps add rule objects
+ final String handle1Rule1 = "11";
+
+ final String handle1Rule2 = "12";
+
+ final String handle2Rule1 = "21";
+
+ final String handle2Rule2 = "22";
+
+ final ArrayList handlesForRules = new ArrayList();
+
+ WorkingMemory workingMemory;
+
+ Rule rule1;
+
+ Rule rule2;
+
+ final Context context1 = new Context( 1 );
+
+ final Context context2 = new Context( 1 );
+
+ public void setUp() throws Exception {
+ this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ this.wm1 = this.ruleBase.newWorkingMemory();
+ this.wm2 = this.ruleBase.newWorkingMemory();
+ this.wm3 = this.ruleBase.newWorkingMemory();
+ this.wm4 = this.ruleBase.newWorkingMemory();
+ // add rules section
+ this.ruleBaseAddRule = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ this.workingMemory = this.ruleBaseAddRule.newWorkingMemory();
+ // rules
+ final ClassObjectType contextType = new ClassObjectType( Context.class );
+ final Evaluator integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+ // rule 1
+ // fires on context.state == integer(1)
+ this.rule1 = new Rule( "rule1" );
+ final Column contextColumnRule1 = new Column( 0,
+ contextType,
+ "context1" );
+ contextColumnRule1.addConstraint( getLiteralConstraint( contextColumnRule1,
+ "state",
+ new Integer( 1 ),
+ integerEqualEvaluator ) );
+ this.rule1.addPattern( contextColumnRule1 );
+ final Declaration contextRule1Declaration = this.rule1.getDeclaration( "context1" );
+ this.rule1.setConsequence( new Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -143645020218500159L;
+
+ public void evaluate(final KnowledgeHelper drools,
+ final WorkingMemory workingMemory) throws ConsequenceException {
+ try {
+ final Rule rule = drools.getRule();
+ final Tuple tuple = drools.getTuple();
+
+ final Context dummy = (Context) drools.get( contextRule1Declaration );
+ if ( dummy == LeapsRuleBaseTest.this.context1 ) {
+ LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle1Rule1 );
+ } else if ( dummy == LeapsRuleBaseTest.this.context2 ) {
+ LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle2Rule1 );
+ }
+
+ } catch ( final Exception e ) {
+ throw new ConsequenceException( e );
+ }
+ }
+
+ } );
+ this.rule2 = new Rule( "rule2" );
+ final Column contextColumnRule2 = new Column( 0,
+ contextType,
+ "context2" );
+ contextColumnRule2.addConstraint( getLiteralConstraint( contextColumnRule2,
+ "state",
+ new Integer( 1 ),
+ integerEqualEvaluator ) );
+ this.rule2.addPattern( contextColumnRule2 );
+ final Declaration contextRule2Declaration = this.rule2.getDeclaration( "context2" );
+ this.rule2.setConsequence( new Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6203944847152159644L;
+
+ public void evaluate(final KnowledgeHelper drools,
+ final WorkingMemory workingMemory) throws ConsequenceException {
+ try {
+ final Rule rule = drools.getRule();
+ final Tuple tuple = drools.getTuple();
+
+ final Context dummy = (Context) drools.get( contextRule2Declaration );
+ if ( dummy == LeapsRuleBaseTest.this.context1 ) {
+ LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle1Rule2 );
+ } else if ( dummy == LeapsRuleBaseTest.this.context2 ) {
+ LeapsRuleBaseTest.this.handlesForRules.add( LeapsRuleBaseTest.this.handle2Rule2 );
+ }
+
+ } catch ( final Exception e ) {
+ throw new ConsequenceException( e );
+ }
+ }
+
+ } );
+ }
+
+ public void testKeepReference() throws Exception {
+ /* Make sure the RuleBase is referencing all 4 Working Memories */
+ assertLength( 4,
+ this.ruleBase.getWorkingMemories() );
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm1 ) );
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm2 ) );
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm4 ) );
+ }
+
+ public void testWeakReference() throws Exception {
+ /* nulling these two so the keys should get garbage collected */
+ this.wm2 = null;
+ this.wm4 = null;
+
+ /* Run GC */
+ System.gc();
+ Thread.sleep( 200 ); // Shouldn't need to sleep, but put it in anyway
+
+ /* Check we now only have two keys */
+ assertLength( 2,
+ this.ruleBase.getWorkingMemories() );
+
+ /* Make sure the correct keys were valid */
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm1 ) );
+ assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm2 ) );
+ assertTrue( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+ assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm4 ) );
+
+ }
+
+ public void testDispose() throws Exception {
+ /*
+ * Now lets test the dispose method on the WorkingMemory itself. dispose
+ * doesn't need GC
+ */
+ this.wm3.dispose();
+
+ /* Check only wm3 was valid */
+ assertLength( 3,
+ this.ruleBase.getWorkingMemories() );
+ assertFalse( this.ruleBase.getWorkingMemories().contains( this.wm3 ) );
+ }
+
+ public void testNoKeepReference() throws Exception {
+ final WorkingMemory wm5 = this.ruleBase.newWorkingMemory( false );
+ final WorkingMemory wm6 = this.ruleBase.newWorkingMemory( false );
+ assertLength( 4,
+ this.ruleBase.getWorkingMemories() );
+ assertFalse( this.ruleBase.getWorkingMemories().contains( wm5 ) );
+ assertFalse( this.ruleBase.getWorkingMemories().contains( wm6 ) );
+ }
+
+ public void testAddRuleBeforeFacts() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ this.workingMemory.assertObject( this.context1 );
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleMixedWithFacts() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ this.workingMemory.assertObject( this.context1 );
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleAfterFacts() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+ this.workingMemory.assertObject( this.context1 );
+ this.workingMemory.assertObject( this.context2 );
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleBeforeFactsFiring() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleMixedWithFactsFiring1() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleMixedWithFactsFiring2() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context2 );
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ public void testAddRuleAfterFactsFiring() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+ this.workingMemory.assertObject( this.context1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ // firing
+ this.workingMemory.fireAllRules();
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 4,
+ this.handlesForRules.size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule1 ) );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator) {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ final FieldValue field = new MockField( fieldValue );
+
+ return new LiteralConstraint( extractor,
+ evaluator,
+ field );
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsTupleTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,128 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.common.AgendaItem;
+
+/**
+ * @author Alexander Bagerman
+ */
+public class LeapsTupleTest extends TestCase {
+
+ LeapsTuple tuple;
+
+ LeapsFactHandle h1;
+
+ LeapsFactHandle h2;
+
+ LeapsFactHandle h3;
+
+ LeapsFactHandle h4;
+
+ LeapsFactHandle hOutsider;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.h1 = new LeapsFactHandle( 1,
+ "one" );
+ this.h2 = new LeapsFactHandle( 2,
+ "two" );
+ this.h3 = new LeapsFactHandle( 3,
+ "three" );
+ this.h4 = new LeapsFactHandle( 4,
+ "four" );
+ final LeapsFactHandle arr[] = {this.h1, this.h2, this.h3, this.h4};
+ this.tuple = new LeapsTuple( arr,
+ null,
+ null );
+
+ this.hOutsider = new LeapsFactHandle( 9876,
+ "outsider" );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.dependsOn(FactHandle)'
+ */
+ public void testDependsOn() {
+ assertTrue( this.tuple.dependsOn( this.h3 ) );
+ assertFalse( this.tuple.dependsOn( this.hOutsider ) );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.get(int)'
+ */
+ public void testGetInt() {
+ assertEquals( this.tuple.get( 3 ),
+ this.h4 );
+
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.get(Declaration)'
+ */
+ public void testGetDeclaration() {
+
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.getFactHandles()'
+ */
+ public void testGetFactHandles() {
+ final FactHandle[] arr = this.tuple.getFactHandles();
+ for ( int i = 0; i < arr.length; i++ ) {
+ assertEquals( arr[0],
+ this.h1 );
+ assertEquals( arr[1],
+ this.h2 );
+ assertEquals( arr[2],
+ this.h3 );
+ assertEquals( arr[3],
+ this.h4 );
+
+ }
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.isActivationNull()'
+ */
+ public void testIsActivationNull() {
+ final AgendaItem item = new AgendaItem( 0L,
+ this.tuple,
+ null,
+ null );
+ assertTrue( this.tuple.isActivationNull() );
+ this.tuple.setActivation( item );
+ assertFalse( this.tuple.isActivationNull() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.LeapsTuple.equals(Object)'
+ */
+ public void testEqualsObject() {
+ final LeapsFactHandle arr[] = {this.h1, this.h2, this.h3, this.h4};
+ final LeapsTuple tupleToCompare = new LeapsTuple( arr,
+ null,
+ null );
+ assertEquals( this.tuple,
+ tupleToCompare );
+
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LeapsWorkingMemoryTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,68 @@
+package org.drools.leaps;
+
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.common.EqualityKey;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.TruthMaintenanceSystem;
+
+public class LeapsWorkingMemoryTest extends TestCase {
+ /*
+ * @see JBRULES-356
+ */
+ public void testBasicWorkingMemoryActions() {
+ final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) RuleBaseFactory.newRuleBase( RuleBase.LEAPS ).newWorkingMemory();
+ final TruthMaintenanceSystem tms = workingMemory.getTruthMaintenanceSystem();
+ final String string = "test";
+ FactHandle fd = workingMemory.assertObject( string );
+
+ assertEquals( 1,
+ tms.getAssertMap().size() );
+ EqualityKey key = tms.get( string );
+ assertSame( fd,
+ key.getFactHandle() );
+ assertNull( key.getOtherFactHandle() );
+
+ workingMemory.modifyObject( fd,
+ string );
+
+ assertEquals( 1,
+ tms.getAssertMap().size() );
+ key = tms.get( string );
+ assertSame( fd,
+ key.getFactHandle() );
+ assertNull( key.getOtherFactHandle() );
+
+ workingMemory.retractObject( fd );
+
+ assertEquals( 0,
+ tms.getAssertMap().size() );
+ key = tms.get( string );
+ assertNull( key );
+
+ fd = workingMemory.assertObject( string );
+
+ assertEquals( 1,
+ tms.getAssertMap().size() );
+
+ assertEquals( 1,
+ tms.getAssertMap().size() );
+ key = tms.get( string );
+ assertSame( fd,
+ key.getFactHandle() );
+ assertNull( key.getOtherFactHandle() );
+ }
+
+ public void testId() {
+ final LeapsRuleBase ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ InternalWorkingMemory workingMemory = (InternalWorkingMemory) ruleBase.newWorkingMemory();
+ assertEquals( 0,
+ workingMemory.getId() );
+ workingMemory = (InternalWorkingMemory) ruleBase.newWorkingMemory();
+ assertEquals( 1,
+ workingMemory.getId() );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/LogicalAssertionTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,367 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+
+import org.drools.DroolsTestCase;
+import org.drools.FactException;
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.Activation;
+import org.drools.spi.Consequence;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+
+/**
+ * @author Alexander Bagerman
+ */
+public class LogicalAssertionTest extends DroolsTestCase {
+
+ Consequence consequence;
+
+ LeapsRuleBase ruleBase;
+
+ LeapsWorkingMemory workingMemory;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+ this.workingMemory = (LeapsWorkingMemory) this.ruleBase.newWorkingMemory();
+ this.consequence = new Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3536436180370109113L;
+
+ public void evaluate(final KnowledgeHelper knowledgeHelper,
+ final WorkingMemory workingMemory) {
+ // do nothing
+ }
+ };
+ }
+
+ public void testEqualsMap() throws Exception {
+ // create a RuleBase with a single ObjectTypeNode we attach a
+ // MockObjectSink so we can detect assertions and retractions
+
+ final Rule rule1 = new Rule( "test-rule1" );
+
+ rule1.setConsequence( this.consequence );
+
+ final LeapsRule leapsRule1 = new LeapsRule( rule1,
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList() );
+
+ final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
+ PropagationContext context1;
+ LeapsTuple tuple1;
+
+ final String logicalString1 = new String( "logical" );
+ final FactHandle handle1 = ((LeapsFactHandleFactory) this.ruleBase.getFactHandleFactory()).newFactHandle( logicalString1 );
+ context1 = new PropagationContextImpl( 1,
+ PropagationContext.ASSERTION,
+ rule1,
+ null );
+ factHandles[0] = (LeapsFactHandle) handle1;
+ tuple1 = new LeapsTuple( factHandles,
+ leapsRule1,
+ context1 );
+ this.workingMemory.assertTuple( tuple1 );
+ FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+ false,
+ true,
+ null,
+ this.workingMemory.getAgenda().getActivations()[0] );
+
+ final String logicalString2 = new String( "logical" );
+ FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+ false,
+ true,
+ rule1,
+ this.workingMemory.getAgenda().getActivations()[0] );
+ factHandles[0] = (LeapsFactHandle) logicalHandle2;
+ tuple1 = new LeapsTuple( factHandles,
+ leapsRule1,
+ context1 );
+ this.workingMemory.assertTuple( tuple1 );
+
+ assertSame( logicalHandle1,
+ logicalHandle2 );
+
+ // little sanity check using normal assert
+ logicalHandle1 = this.workingMemory.assertObject( logicalString1 );
+ logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+ assertNotSame( logicalHandle1,
+ logicalHandle2 );
+
+ }
+
+ /**
+ * This tests that Stated asserts always take precedent
+ *
+ * @throws Exception
+ */
+ public void testStatedOverride() throws Exception {
+ final Rule rule1 = new Rule( "test-rule1" );
+
+ rule1.setConsequence( this.consequence );
+
+ final LeapsRule leapsRule1 = new LeapsRule( rule1,
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList() );
+
+ final LeapsFactHandle[] factHandles = new LeapsFactHandle[1];
+ PropagationContext context1;
+ LeapsTuple tuple1;
+
+ String logicalString1 = new String( "logical" );
+ final FactHandle handle1 = ((LeapsFactHandleFactory) this.ruleBase.getFactHandleFactory()).newFactHandle( logicalString1 );
+ context1 = new PropagationContextImpl( 1,
+ PropagationContext.ASSERTION,
+ rule1,
+ null );
+ factHandles[0] = (LeapsFactHandle) handle1;
+ tuple1 = new LeapsTuple( factHandles,
+ leapsRule1,
+ context1 );
+ this.workingMemory.assertTuple( tuple1 );
+ FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+ false,
+ true,
+ null,
+ this.workingMemory.getAgenda().getActivations()[0] );
+
+ String logicalString2 = new String( "logical" );
+ FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+
+ // Should keep the same handle when overriding
+ assertSame( logicalHandle1,
+ logicalHandle2 );
+
+ // so while new STATED assertion is equal
+ assertEquals( logicalString1,
+ this.workingMemory.getObject( logicalHandle2 ) );
+ // they are not - not identity same - leaps can not store two objects if
+ // handles are the same
+ assertNotSame( logicalString1,
+ this.workingMemory.getObject( logicalHandle2 ) );
+
+ assertSame( logicalString2,
+ this.workingMemory.getObject( logicalHandle2 ) );
+
+ // Test that a logical assertion cannot override a STATED assertion
+ factHandles[0] = (LeapsFactHandle) logicalHandle2;
+ tuple1 = new LeapsTuple( factHandles,
+ leapsRule1,
+ context1 );
+ this.workingMemory.assertTuple( tuple1 );
+
+ logicalString2 = new String( "logical" );
+ logicalHandle2 = this.workingMemory.assertObject( logicalString2 );
+
+ // This logical assertion will be ignored as there is already
+ // an equals STATED assertion.
+ logicalString1 = new String( "logical" );
+ logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+ false,
+ true,
+ null,
+ this.workingMemory.getAgenda().getActivations()[0] );
+ // Already an equals object but not identity same, so will do nothing
+ // and return null
+ assertNull( logicalHandle1 );
+
+ // // Alreyad identify same so return previously assigned handle
+ // logicalHandle1 = this.workingMemory.assertObject( logicalString2,
+ // false,
+ // true,
+ // null,
+ // this.workingMemory.getAgenda().getActivations()[0] );
+ // // return the matched handle
+ // assertSame( logicalHandle2,
+ // logicalHandle1 );
+ //
+ // this.workingMemory.retractObject( handle1 );
+ //
+ // // Should keep the same handle when overriding
+ // assertSame( logicalHandle1,
+ // logicalHandle2 );
+ //
+ // // so while new STATED assertion is equal
+ // assertEquals( logicalString1,
+ // this.workingMemory.getObject( logicalHandle2 ) );
+ //
+ // // they are not identity same
+ // assertNotSame( logicalString1,
+ // this.workingMemory.getObject( logicalHandle2 ) );
+ //
+ }
+
+ public void testRetract() throws Exception {
+ final Rule rule1 = new Rule( "test-rule1" );
+ // create the first agendaItem which will justify the fact "logical"
+ rule1.setConsequence( this.consequence );
+
+ final LeapsRule leapsRule1 = new LeapsRule( rule1,
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList() );
+
+ final LeapsFactHandle tuple1FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
+ final LeapsFactHandle tuple2FactHandle = (LeapsFactHandle) this.workingMemory.assertObject( "tuple2 object" );
+ final LeapsFactHandle[] factHandlesTuple1 = new LeapsFactHandle[1];
+ final LeapsFactHandle[] factHandlesTuple2 = new LeapsFactHandle[1];
+ factHandlesTuple1[0] = tuple1FactHandle;
+ factHandlesTuple2[0] = tuple2FactHandle;
+
+ final PropagationContext context = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule1,
+ null );
+ LeapsTuple tuple1 = new LeapsTuple( factHandlesTuple1,
+ leapsRule1,
+ context );
+ final LeapsTuple tuple2 = new LeapsTuple( factHandlesTuple2,
+ leapsRule1,
+ context );
+ this.workingMemory.assertTuple( tuple1 );
+ final Activation activation1 = this.workingMemory.getAgenda().getActivations()[0];
+
+ // Assert the logical "logical" fact
+ final String logicalString1 = new String( "logical" );
+ final FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+ false,
+ true,
+ rule1,
+ activation1 );
+ assertEquals( 3,
+ this.workingMemory.getObjects().size() );
+
+ // create the second agendaItem to justify the "logical" fact
+ final Rule rule2 = new Rule( "test-rule2" );
+ rule2.setConsequence( this.consequence );
+ final PropagationContext context2 = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule2,
+ null );
+ tuple1 = new LeapsTuple( factHandlesTuple2,
+ leapsRule1,
+ context2 );
+ this.workingMemory.assertTuple( tuple1 );
+ final Activation activation2 = this.workingMemory.getAgenda().getActivations()[1];
+ //
+ final String logicalString2 = new String( "logical" );
+ final FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+ false,
+ true,
+ rule1,
+ activation2 );
+ // "logical" should only appear once
+ assertEquals( 3,
+ this.workingMemory.getObjects().size() );
+
+ // retract the logical object
+ this.workingMemory.retractObject( logicalHandle2 );
+
+ // The logical object should never appear
+ assertEquals( 2,
+ this.workingMemory.getObjects().size() );
+
+ }
+
+ public void testMultipleLogicalRelationships() throws FactException {
+ final Rule rule1 = new Rule( "test-rule1" );
+ // create the first agendaItem which will justify the fact "logical"
+ rule1.setConsequence( this.consequence );
+
+ final LeapsRule leapsRule1 = new LeapsRule( rule1,
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList(),
+ new ArrayList() );
+
+ final LeapsFactHandle tuple1Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple1 object" );
+ final LeapsFactHandle tuple2Fact = (LeapsFactHandle) this.workingMemory.assertObject( "tuple2 object" );
+ final LeapsFactHandle[] tuple1Handles = new LeapsFactHandle[1];
+ final LeapsFactHandle[] tuple2Handles = new LeapsFactHandle[1];
+ tuple1Handles[0] = tuple1Fact;
+ tuple2Handles[0] = tuple2Fact;
+
+ final PropagationContext context1 = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule1,
+ null );
+ final LeapsTuple tuple1 = new LeapsTuple( tuple1Handles,
+ leapsRule1,
+ context1 );
+ this.workingMemory.assertTuple( tuple1 );
+ final Activation activation1 = this.workingMemory.getAgenda().getActivations()[0];
+
+ // Assert the logical "logical" fact
+ final String logicalString1 = new String( "logical" );
+ final FactHandle logicalHandle1 = this.workingMemory.assertObject( logicalString1,
+ false,
+ true,
+ rule1,
+ activation1 );
+
+ // create the second agendaItem to justify the "logical" fact
+ final Rule rule2 = new Rule( "test-rule2" );
+ rule2.setConsequence( this.consequence );
+ final PropagationContext context2 = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule2,
+ null );
+ final LeapsTuple tuple2 = new LeapsTuple( tuple2Handles,
+ leapsRule1,
+ context2 );
+ this.workingMemory.assertTuple( tuple2 );
+ // "logical" should only appear once
+ final Activation activation2 = this.workingMemory.getAgenda().getActivations()[1];
+ //
+ final String logicalString2 = new String( "logical" );
+ final FactHandle logicalHandle2 = this.workingMemory.assertObject( logicalString2,
+ false,
+ true,
+ rule2,
+ activation2 );
+
+ assertEquals( 3,
+ this.workingMemory.getObjects().size() );
+ //
+ this.workingMemory.retractObject( tuple1Fact );
+ // check "logical" is still in the system
+ assertEquals( 2,
+ this.workingMemory.getObjects().size() );
+
+ // now remove that final justification
+ this.workingMemory.retractObject( tuple2Fact );
+ // "logical" fact should no longer be in the system
+ assertEquals( 0,
+ this.workingMemory.getObjects().size() );
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryResultsTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,203 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.FactHandle;
+import org.drools.PackageIntegrationException;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.rule.Column;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.MockField;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class QueryResultsTest extends TestCase {
+ public void testQueryTerminalNode() throws PackageIntegrationException {
+ final LeapsRuleBase ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ final ClassObjectType cheeseObjectType = new ClassObjectType( Cheese.class );
+ final Evaluator evaluator = ValueType.STRING_TYPE.getEvaluator( Operator.EQUAL );
+ // fires on context.state == integer(1)
+ final Query query = new Query( "query-1" );
+
+ final Column cheeseColumn = new Column( 0,
+ cheeseObjectType,
+ "cheese" );
+ cheeseColumn.addConstraint( getLiteralConstraint( cheeseColumn,
+ "type",
+ "stilton",
+ evaluator ) );
+ query.addPattern( cheeseColumn );
+
+ ruleBase.addRule( query );
+
+ final WorkingMemory workingMemory = ruleBase.newWorkingMemory();
+
+ workingMemory.fireAllRules();
+
+ LeapsQueryResults results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertNull( results );
+
+ final Cheese stilton1 = new Cheese( "stilton",
+ 100 );
+
+ final FactHandle handle1 = workingMemory.assertObject( stilton1 );
+
+ workingMemory.fireAllRules();
+
+ results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertEquals( 1,
+ results.size() );
+
+ final Cheese cheddar = new Cheese( "cheddar",
+ 55 );
+ workingMemory.assertObject( cheddar );
+
+ workingMemory.fireAllRules();
+
+ results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertEquals( 1,
+ results.size() );
+
+ final Cheese stilton2 = new Cheese( "stilton",
+ 5 );
+
+ final FactHandle handle2 = workingMemory.assertObject( stilton2 );
+
+ workingMemory.fireAllRules();
+
+ results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertEquals( 2,
+ results.size() );
+
+ LeapsQueryResult result = (LeapsQueryResult) results.get( 0 );
+
+ assertEquals( 1,
+ result.size() );
+
+ boolean wasStilton1 = (stilton1 == result.get( 0 ));
+
+ // assertSame( stilton1, result.get( 0 ) );
+
+ result = (LeapsQueryResult) results.get( 1 );
+
+ boolean wasStilton2 = (stilton2 == result.get( 0 ));
+
+ assertEquals( 1,
+ result.size() );
+
+ // assertSame( stilton2, result.get( 0 ) );
+ assertTrue( (wasStilton1 && wasStilton2) || (!wasStilton1 && !wasStilton2) );
+ Object result1 = null, result2 = null;
+ int i = 0;
+ for ( final Iterator it = results.iterator(); it.hasNext(); ) {
+ result = (LeapsQueryResult) it.next();
+ assertEquals( 1,
+ result.size() );
+ if ( i == 0 ) {
+ result1 = result.get( 0 );
+ } else {
+ result2 = result.get( 0 );
+ }
+ i++;
+ }
+ wasStilton1 = (stilton1 == result1);
+ wasStilton2 = (stilton2 == result2);
+ assertTrue( (wasStilton1 && wasStilton2) || (!wasStilton1 && !wasStilton2) );
+
+ workingMemory.retractObject( handle1 );
+
+ workingMemory.fireAllRules();
+
+ results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertEquals( 1,
+ results.size() );
+
+ workingMemory.retractObject( handle2 );
+
+ workingMemory.fireAllRules();
+
+ results = (LeapsQueryResults) workingMemory.getQueryResults( "query-1" );
+
+ assertNull( results );
+ }
+
+ public class Cheese {
+ private String type;
+
+ private int price;
+
+ public Cheese(final String type,
+ final int price) {
+ super();
+ this.type = type;
+ this.price = price;
+ }
+
+ public int getPrice() {
+ return this.price;
+ }
+
+ public String getType() {
+ return this.type;
+ }
+
+ public String toString() {
+ return "[Cheese type='" + this.type + "' price='" + this.price + "']";
+ }
+
+ }
+
+ private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator) {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ final FieldValue field = new MockField( fieldValue );
+
+ return new LiteralConstraint( extractor,
+ evaluator,
+ field );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/QueryTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,172 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldExtractor;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.Operator;
+import org.drools.examples.manners.Context;
+import org.drools.rule.Column;
+import org.drools.rule.Declaration;
+import org.drools.rule.LiteralConstraint;
+import org.drools.rule.Query;
+import org.drools.rule.Rule;
+import org.drools.spi.AlphaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.FieldExtractor;
+import org.drools.spi.FieldValue;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.MockField;
+import org.drools.spi.Tuple;
+
+/**
+ *
+ * @author Alexander Bagerman
+ *
+ */
+public class QueryTest extends DroolsTestCase {
+ LeapsRuleBase ruleBase;
+ LeapsRuleBase ruleBaseAddRule;
+
+ WorkingMemory wm1;
+
+ // leaps add rule objects
+ final String handle1Rule1 = "11";
+
+ final String handle1Rule2 = "12";
+
+ final String handle2Rule1 = "21";
+
+ final String handle2Rule2 = "22";
+
+ final ArrayList handlesForRules = new ArrayList();
+
+ WorkingMemory workingMemory;
+
+ Rule rule1;
+
+ Rule rule2;
+
+ final Context context1 = new Context( 1 );
+
+ final Context context2 = new Context( 1 );
+
+ public void setUp() throws Exception {
+ this.ruleBase = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ this.wm1 = this.ruleBase.newWorkingMemory();
+ // add rules section
+ this.ruleBaseAddRule = (LeapsRuleBase) RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ this.workingMemory = this.ruleBaseAddRule.newWorkingMemory();
+ // rules
+ final ClassObjectType contextType = new ClassObjectType( Context.class );
+ final Evaluator integerEqualEvaluator = ValueType.INTEGER_TYPE.getEvaluator( Operator.EQUAL );
+ // rule 1
+ // fires on context.state == integer(1)
+ this.rule1 = new Query( "query-to-execute" );
+ final Column contextColumnRule1 = new Column( 0,
+ contextType,
+ "context1" );
+ contextColumnRule1.addConstraint( getLiteralConstraint( contextColumnRule1,
+ "state",
+ new Integer( 1 ),
+ integerEqualEvaluator ) );
+ this.rule1.addPattern( contextColumnRule1 );
+
+ this.rule2 = new Rule( "rule2" );
+ final Column contextColumnRule2 = new Column( 0,
+ contextType,
+ "context2" );
+ contextColumnRule2.addConstraint( getLiteralConstraint( contextColumnRule2,
+ "state",
+ new Integer( 1 ),
+ integerEqualEvaluator ) );
+ this.rule2.addPattern( contextColumnRule2 );
+ final Declaration contextRule2Declaration = this.rule2.getDeclaration( "context2" );
+ this.rule2.setConsequence( new Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5839841224218714327L;
+
+ public void evaluate(final KnowledgeHelper drools,
+ final WorkingMemory workingMemory) throws ConsequenceException {
+ try {
+ final Rule rule = drools.getRule();
+ final Tuple tuple = drools.getTuple();
+
+ final Context dummy = (Context) drools.get( contextRule2Declaration );
+ if ( dummy == QueryTest.this.context1 ) {
+ QueryTest.this.handlesForRules.add( QueryTest.this.handle1Rule2 );
+ } else if ( dummy == QueryTest.this.context2 ) {
+ QueryTest.this.handlesForRules.add( QueryTest.this.handle2Rule2 );
+ }
+
+ } catch ( final Exception e ) {
+ throw new ConsequenceException( e );
+ }
+ }
+
+ } );
+ }
+
+ public void testAddRuleBeforeFacts() throws Exception {
+
+ assertEquals( 0,
+ this.handlesForRules.size() );
+
+ this.ruleBaseAddRule.addRule( this.rule1 );
+ this.ruleBaseAddRule.addRule( this.rule2 );
+ this.workingMemory.assertObject( this.context1 );
+ this.workingMemory.assertObject( this.context2 );
+ // firing
+ this.workingMemory.fireAllRules();
+ // finally everything should be filled
+ assertEquals( 2,
+ this.handlesForRules.size() );
+ assertEquals( 2,
+ this.workingMemory.getQueryResults( "query-to-execute" ).size() );
+ assertTrue( this.handlesForRules.contains( this.handle1Rule2 ) );
+ assertTrue( this.handlesForRules.contains( this.handle2Rule2 ) );
+ }
+
+ private AlphaNodeFieldConstraint getLiteralConstraint(final Column column,
+ final String fieldName,
+ final Object fieldValue,
+ final Evaluator evaluator) {
+ final Class clazz = ((ClassObjectType) column.getObjectType()).getClassType();
+
+ final FieldExtractor extractor = new ClassFieldExtractor( clazz,
+ fieldName );
+
+ final FieldValue field = new MockField( fieldValue );
+
+ return new LiteralConstraint( extractor,
+ evaluator,
+ field );
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/SchedulerTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,177 @@
+package org.drools.leaps;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.drools.DroolsTestCase;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.WorkingMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.rule.Rule;
+import org.drools.spi.Duration;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.Tuple;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class SchedulerTest extends DroolsTestCase {
+ public void testScheduledActivation() throws Exception {
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+
+ final Rule rule = new Rule( "scheduled-test-rule" );
+ final List data = new ArrayList();
+
+ // add consequence
+ rule.setConsequence( new org.drools.spi.Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1991405634414239175L;
+
+ public void evaluate(final KnowledgeHelper knowledgeHelper,
+ final WorkingMemory workingMemory) {
+ data.add( "tested" );
+ }
+ } );
+
+ /* 1/10th of a second */
+ final Duration duration = new Duration() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1650013015631329969L;
+
+ public long getDuration(Tuple tuple) {
+ return 100;
+ }
+ };
+ rule.setDuration( duration );
+
+ final PropagationContext context = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule,
+ null );
+
+ final LeapsFactHandle tupleFactHandle = (LeapsFactHandle) workingMemory.assertObject( "tuple object" );
+ final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
+ factHandlesTuple[0] = tupleFactHandle;
+
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+ final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
+ (LeapsRule) leapsRules.get( 0 ),
+ context );
+
+ assertEquals( 0,
+ data.size() );
+
+ workingMemory.assertTuple( tuple );
+
+ // sleep for 2 seconds
+ Thread.sleep( 300 );
+
+ // now check for update
+ assertEquals( 1,
+ data.size() );
+ }
+
+ public void testDoLoopScheduledActivation() throws Exception {
+ final RuleBase ruleBase = RuleBaseFactory.newRuleBase( RuleBase.LEAPS );
+
+ final LeapsWorkingMemory workingMemory = (LeapsWorkingMemory) ruleBase.newWorkingMemory();
+
+ final Rule rule = new Rule( "do-loop-scheduled-test-rule" );
+ final List data = new ArrayList();
+
+ /* 1/10th of a second */
+ final Duration duration = new Duration() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = -65249353062404118L;
+
+ public long getDuration(Tuple tuple) {
+ return 100;
+ }
+ };
+
+ rule.setDuration( duration );
+
+ // add consequence
+ rule.setConsequence( new org.drools.spi.Consequence() {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 5431138295939934840L;
+
+ public void evaluate(final KnowledgeHelper knowledgeHelper,
+ final WorkingMemory workingMemory) {
+ /* on first invoke add another one to the agenda */
+ if ( data.size() < 3 ) {
+ final PropagationContext context2 = new PropagationContextImpl( 0,
+ 0,
+ rule,
+ knowledgeHelper.getActivation() );
+
+ final LeapsFactHandle tupleFactHandleIn = (LeapsFactHandle) workingMemory.assertObject( "tuple object in" );
+ final LeapsFactHandle[] factHandlesTupleIn = new LeapsFactHandle[1];
+ factHandlesTupleIn[0] = tupleFactHandleIn;
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+ final LeapsTuple tupleIn = new LeapsTuple( factHandlesTupleIn,
+ (LeapsRule) leapsRules.get( 0 ),
+ context2 );
+ ((LeapsWorkingMemory) workingMemory).assertTuple( tupleIn );
+ }
+ data.add( "tested" );
+ }
+ } );
+
+ final PropagationContext context = new PropagationContextImpl( 0,
+ PropagationContext.ASSERTION,
+ rule,
+ null );
+
+ final LeapsFactHandle tupleFactHandle = (LeapsFactHandle) workingMemory.assertObject( "tuple object" );
+ final LeapsFactHandle[] factHandlesTuple = new LeapsFactHandle[1];
+ factHandlesTuple[0] = tupleFactHandle;
+
+ final ArrayList leapsRules = (ArrayList) LeapsBuilder.processRule( rule );
+ final LeapsTuple tuple = new LeapsTuple( factHandlesTuple,
+ (LeapsRule) leapsRules.get( 0 ),
+ context );
+
+ workingMemory.assertTuple( tuple );
+
+ assertEquals( 0,
+ data.size() );
+
+ // sleep for 0.5 seconds
+ Thread.sleep( 1000 );
+
+ // now check for update
+ assertEquals( 4,
+ data.size() );
+
+ }
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableIteratorTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,355 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.leaps.conflict.LoadOrderConflictResolver;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableIteratorTest extends TestCase {
+
+ DefaultFactHandle h1;
+
+ DefaultFactHandle h1000;
+
+ DefaultFactHandle h100;
+
+ DefaultFactHandle h10;
+
+ Table testTable;
+
+ protected void setUp() {
+ this.testTable = new Table( LoadOrderConflictResolver.getInstance() );
+ this.h1 = new DefaultFactHandle( 1,
+ "1" );
+ this.h1000 = new DefaultFactHandle( 1000,
+ "1000" );
+ this.h100 = new DefaultFactHandle( 100,
+ "100" );
+ this.h10 = new DefaultFactHandle( 10,
+ "10" );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools..util.TableIterator.TableIterator()'
+ */
+ public void testTableIterator() {
+ final IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( null,
+ null );
+ assertFalse( it.hasNext() );
+ assertTrue( it.isEmpty() );
+ }
+
+ public void testGetDominantFactIterator() {
+ final Iterator it = Table.singleItemIterator( this.h1000 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1000 );
+ assertFalse( it.hasNext() );
+ }
+
+ /*
+ * Test method for
+ * 'org.drools..util.TableIterator.TableIterator(TableRecord)'
+ */
+ public void testTableIteratorTableRecord() {
+ final IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertTrue( it.hasNext() );
+ assertFalse( it.isEmpty() );
+ assertEquals( this.h1,
+ it.next() );
+ assertFalse( it.hasNext() );
+ assertFalse( it.isEmpty() );
+
+ }
+
+ /*
+ * Test method for
+ * 'org.drools..util.TableIterator.TableIterator(TableRecord,
+ * TableRecord, TableRecord)'
+ */
+ public void testTableIteratorTableRecordTableRecordTableRecord() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertTrue( it.hasNext() );
+ assertFalse( it.isEmpty() );
+ assertEquals( this.h1,
+ it.next() );
+ assertFalse( it.hasNext() );
+ assertFalse( it.isEmpty() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertFalse( it.isEmpty() );
+ assertTrue( it.hasNext() );
+ assertEquals( this.h1000,
+ it.next() );
+ assertTrue( it.hasNext() );
+ assertEquals( this.h100,
+ it.next() );
+ assertTrue( it.hasNext() );
+ assertEquals( this.h10,
+ it.next() );
+ assertTrue( it.hasNext() );
+ assertEquals( this.h1,
+ it.next() );
+ assertFalse( it.hasNext() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertFalse( it.isEmpty() );
+ assertTrue( it.hasNext() );
+ assertTrue( it.hasNext() );
+ assertEquals( this.h1,
+ it.next() );
+ assertFalse( it.hasNext() );
+
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.isEmpty()'
+ */
+ public void testIsEmpty() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertFalse( it.isEmpty() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertFalse( it.isEmpty() );
+ it = new IteratorFromPositionToTableStart( this.testTable.tailRecord,
+ this.testTable.headRecord );
+ assertFalse( it.isEmpty() );
+ it = new IteratorFromPositionToTableStart( null,
+ null );
+ assertTrue( it.isEmpty() );
+
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.reset()'
+ */
+ public void testReset() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.next() );
+ it.reset();
+ assertEquals( this.h1,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertEquals( this.h1000,
+ it.next() );
+ it.reset();
+ assertEquals( this.h1000,
+ it.next() );
+ it.next();
+ it.next();
+ it.reset();
+ assertEquals( this.h1000,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ it.reset();
+ assertEquals( this.h1000,
+ it.next() );
+ it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertEquals( this.h1,
+ it.next() );
+ it.reset();
+ assertEquals( this.h1,
+ it.next() );
+
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.hasNext()'
+ */
+ public void testHasNext() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertTrue( it.hasNext() );
+ assertFalse( it.isEmpty() );
+ assertEquals( this.h1,
+ it.next() );
+ assertFalse( it.hasNext() );
+ assertFalse( it.isEmpty() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertTrue( it.hasNext() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertTrue( it.hasNext() );
+ it = new IteratorFromPositionToTableStart( null,
+ null );
+ assertFalse( it.hasNext() );
+ it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertTrue( it.hasNext() );
+
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.next()'
+ */
+ public void testNext() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertEquals( this.h1000,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.next() );
+ it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertEquals( this.h1,
+ it.next() );
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.current()'
+ */
+ public void testCurrent() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertEquals( this.h1000,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.next() );
+ it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertEquals( this.h1,
+ it.next() );
+ }
+
+ /*
+ * Test method for 'org.drools..util.TableIterator.peekNext()'
+ */
+ public void testPeekNext() {
+ this.testTable.add( this.h1 );
+ IteratorFromPositionToTableStart it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.peekNext() );
+ assertEquals( this.h1,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.headRecord );
+ assertEquals( this.h1000,
+ it.peekNext() );
+ assertEquals( this.h1000,
+ it.next() );
+ this.testTable.clear();
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h10 );
+ this.testTable.add( this.h100 );
+ it = new IteratorFromPositionToTableStart( this.testTable.headRecord,
+ this.testTable.tailRecord );
+ assertEquals( this.h1,
+ it.peekNext() );
+ assertEquals( this.h1,
+ it.next() );
+ it = new IteratorFromPositionToTableStart( new TableRecord( this.h1 ) );
+ assertEquals( this.h1,
+ it.peekNext() );
+ assertEquals( this.h1,
+ it.next() );
+
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableRecordTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,54 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import junit.framework.TestCase;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableRecordTest extends TestCase {
+
+ public void testConstractor() {
+ final String object = new String( "test object" );
+ final TableRecord record = new TableRecord( object );
+ assertEquals( object,
+ record.object );
+ }
+
+ public void testLeft() {
+ final String object1 = new String( "test object1" );
+ final String object2 = new String( "test object2" );
+ final TableRecord record1 = new TableRecord( object1 );
+ final TableRecord record2 = new TableRecord( object2 );
+ record1.left = record2;
+ assertEquals( object2,
+ record1.left.object );
+ }
+
+ public void testRight() {
+ final String object1 = new String( "test object1" );
+ final String object2 = new String( "test object2" );
+ final TableRecord record1 = new TableRecord( object1 );
+ final TableRecord record2 = new TableRecord( object2 );
+ record1.right = record2;
+ assertEquals( object2,
+ record1.right.object );
+ }
+
+}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TableTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,256 @@
+package org.drools.leaps.util;
+
+/*
+ * Copyright 2005 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Iterator;
+
+import junit.framework.TestCase;
+
+import org.drools.common.DefaultFactHandle;
+import org.drools.examples.manners.Context;
+import org.drools.examples.manners.Guest;
+import org.drools.examples.manners.Hobby;
+import org.drools.examples.manners.Sex;
+import org.drools.leaps.conflict.LoadOrderConflictResolver;
+
+/**
+ * @author Alexander Bagerman
+ */
+
+public class TableTest extends TestCase {
+
+ DefaultFactHandle h1;
+
+ DefaultFactHandle h1000;
+
+ DefaultFactHandle h100;
+
+ DefaultFactHandle h10;
+
+ Table testTable;
+
+ protected void setUp() {
+ this.testTable = new Table( LoadOrderConflictResolver.getInstance() );
+ this.h1 = new DefaultFactHandle( 1,
+ "1" );
+ this.h1000 = new DefaultFactHandle( 1000,
+ "1000" );
+ this.h100 = new DefaultFactHandle( 100,
+ "100" );
+ this.h10 = new DefaultFactHandle( 10,
+ "10" );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.add(Object)'
+ */
+ public void testAddAndContains() {
+ assertFalse( this.testTable.contains( this.h1 ) );
+ this.testTable.add( this.h1 );
+ assertTrue( this.testTable.contains( this.h1 ) );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.remove(Object)'
+ */
+ public void testRemove() {
+ assertFalse( this.testTable.contains( this.h1 ) );
+ this.testTable.add( this.h1 );
+ assertTrue( this.testTable.contains( this.h1 ) );
+ this.testTable.remove( this.h1 );
+ assertFalse( this.testTable.contains( this.h1 ) );
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ assertTrue( this.testTable.contains( this.h100 ) );
+ this.testTable.remove( this.h100 );
+ assertFalse( this.testTable.contains( this.h100 ) );
+ assertTrue( this.testTable.contains( this.h1000 ) );
+ this.testTable.remove( this.h1000 );
+ assertFalse( this.testTable.contains( this.h1000 ) );
+ assertTrue( this.testTable.contains( this.h1 ) );
+ this.testTable.remove( this.h1 );
+ assertFalse( this.testTable.contains( this.h1 ) );
+ final Iterator it = this.testTable.iterator();
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h10 );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.isEmpty()'
+ */
+ public void testIsEmpty() {
+ assertTrue( this.testTable.isEmpty() );
+ this.testTable.add( this.h1 );
+ assertFalse( this.testTable.isEmpty() );
+ this.testTable.remove( this.h1 );
+ assertTrue( this.testTable.isEmpty() );
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ assertFalse( this.testTable.isEmpty() );
+ this.testTable.remove( this.h100 );
+ assertFalse( this.testTable.isEmpty() );
+ this.testTable.remove( this.h1000 );
+ assertFalse( this.testTable.isEmpty() );
+ this.testTable.remove( this.h1 );
+ assertFalse( this.testTable.isEmpty() );
+ this.testTable.remove( this.h10 );
+ assertTrue( this.testTable.isEmpty() );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.headObject'
+ */
+ public void testHeadObject() {
+ this.testTable.add( this.h1 );
+ assertEquals( this.h1,
+ this.testTable.headRecord.object );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ assertEquals( this.h1000,
+ this.testTable.headRecord.object );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.tailObject'
+ */
+ public void testTailObject() {
+ this.testTable.add( this.h1 );
+ assertEquals( this.testTable.tailRecord.object,
+ this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ assertEquals( this.testTable.tailRecord.object,
+ this.h1 );
+ }
+
+ /*
+ * Test method for 'org.drools..util.Table.iterator()'
+ */
+ public void testIterator() {
+ Iterator it;
+ // empty iterator
+ it = this.testTable.iterator();
+ assertFalse( it.hasNext() );
+ // iterate over a single element
+ this.testTable.add( this.h1 );
+ it = this.testTable.iterator();
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1 );
+ assertFalse( it.hasNext() );
+ // several items iterator
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ it = this.testTable.iterator();
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1000 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h100 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h10 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1 );
+ assertFalse( it.hasNext() );
+ }
+
+ public void testTailIterator() {
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+
+ TableIterator it = this.testTable.iteratorFromPositionToTableStart( this.h100,
+ this.h10 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h10 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1 );
+ assertFalse( it.hasNext() );
+ it.reset();
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h100 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h10 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1 );
+ assertFalse( it.hasNext() );
+
+ this.testTable.clear();
+ final DefaultFactHandle fh1 = new DefaultFactHandle( 1,
+ new Guest( "1",
+ Sex.resolve( "m" ),
+ Hobby.resolve( "h2" ) ) );
+ final DefaultFactHandle fh2 = new DefaultFactHandle( 2,
+ new Guest( "1",
+ Sex.resolve( "m" ),
+ Hobby.resolve( "h1" ) ) );
+ final DefaultFactHandle fh3 = new DefaultFactHandle( 3,
+ new Guest( "1",
+ Sex.resolve( "m" ),
+ Hobby.resolve( "h3" ) ) );
+ final DefaultFactHandle fh4 = new DefaultFactHandle( 4,
+ new Guest( "3",
+ Sex.resolve( "f" ),
+ Hobby.resolve( "h2" ) ) );
+ final DefaultFactHandle fhC = new DefaultFactHandle( 5,
+ new Context( "start" ) );
+ this.testTable.add( fh1 );
+ this.testTable.add( fh2 );
+ this.testTable.add( fh3 );
+ this.testTable.add( fh4 );
+ it = this.testTable.iteratorFromPositionToTableStart( fhC,
+ fhC );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ fh4 );
+ }
+
+ public void testHeadIterator() {
+ this.testTable.add( this.h1 );
+ this.testTable.add( this.h1000 );
+ this.testTable.add( this.h100 );
+ this.testTable.add( this.h10 );
+ final TableIterator it = this.testTable.iteratorFromPositionToTableEnd( this.h1 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h10 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h100 );
+ assertTrue( it.hasNext() );
+ assertEquals( it.next(),
+ this.h1000 );
+ assertFalse( it.hasNext() );
+ }
+}
Added: labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java
===================================================================
--- labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java 2006-10-20 17:32:25 UTC (rev 6971)
+++ labs/jbossrules/trunk/drools-leaps/src/test/java/org/drools/leaps/util/TokenStackTest.java 2006-10-20 17:34:03 UTC (rev 6972)
@@ -0,0 +1,312 @@
+package org.drools.leaps.util;
+
+import junit.framework.TestCase;
+
+import org.drools.leaps.LeapsFactHandle;
+import org.drools.leaps.Token;
+
+public class TokenStackTest extends TestCase {
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.empty()'
+ */
+ public void testEmpty() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Token token = new Token( null,
+ new LeapsFactHandle( 3,
+ new Object() ),
+ null );
+ stack.push( token );
+ assertFalse( stack.empty() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.peek()'
+ */
+ public void testPeek() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Object object = new Object();
+ final Token token1 = new Token( null,
+ new LeapsFactHandle( 1,
+ object ),
+ null );
+ stack.push( token1 );
+ final Token token2 = new Token( null,
+ new LeapsFactHandle( 2,
+ object ),
+ null );
+ stack.push( token2 );
+ final Token token10 = new Token( null,
+ new LeapsFactHandle( 10,
+ object ),
+ null );
+ stack.push( token10 );
+ final Token token8 = new Token( null,
+ new LeapsFactHandle( 8,
+ object ),
+ null );
+ stack.push( token8 );
+ final Token token6 = new Token( null,
+ new LeapsFactHandle( 6,
+ object ),
+ null );
+ stack.push( token6 );
+ final Token token3 = new Token( null,
+ new LeapsFactHandle( 3,
+ object ),
+ null );
+ stack.push( token3 );
+ final Token token4 = new Token( null,
+ new LeapsFactHandle( 4,
+ object ),
+ null );
+ stack.push( token4 );
+
+ assertEquals( token4,
+ stack.peek() );
+ stack.pop();
+ assertEquals( token3,
+ stack.peek() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.pop()'
+ */
+ public void testPop() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Object object = new Object();
+ final Token token1 = new Token( null,
+ new LeapsFactHandle( 1,
+ object ),
+ null );
+ stack.push( token1 );
+ final Token token2 = new Token( null,
+ new LeapsFactHandle( 2,
+ object ),
+ null );
+ stack.push( token2 );
+ final Token token10 = new Token( null,
+ new LeapsFactHandle( 10,
+ object ),
+ null );
+ stack.push( token10 );
+ final Token token8 = new Token( null,
+ new LeapsFactHandle( 8,
+ object ),
+ null );
+ stack.push( token8 );
+ final Token token6 = new Token( null,
+ new LeapsFactHandle( 6,
+ object ),
+ null );
+ stack.push( token6 );
+ final Token token3 = new Token( null,
+ new LeapsFactHandle( 3,
+ object ),
+ null );
+ stack.push( token3 );
+ final Token token4 = new Token( null,
+ new LeapsFactHandle( 4,
+ object ),
+ null );
+ stack.push( token4 );
+
+ assertEquals( token4,
+ stack.peek() );
+ stack.pop();
+ assertEquals( token3,
+ stack.peek() );
+ stack.pop();
+ stack.pop();
+ stack.pop();
+ stack.pop();
+ stack.pop();
+ assertEquals( token1,
+ stack.peek() );
+ stack.pop();
+
+ assertTrue( stack.empty() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+ */
+ public void testRemoveBottom() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Object object = new Object();
+ final Token token1 = new Token( null,
+ new LeapsFactHandle( 1,
+ object ),
+ null );
+ stack.push( token1 );
+ final Token token2 = new Token( null,
+ new LeapsFactHandle( 2,
+ object ),
+ null );
+ stack.push( token2 );
+ final Token token10 = new Token( null,
+ new LeapsFactHandle( 10,
+ object ),
+ null );
+ stack.push( token10 );
+ final Token token8 = new Token( null,
+ new LeapsFactHandle( 8,
+ object ),
+ null );
+ stack.push( token8 );
+ final Token token6 = new Token( null,
+ new LeapsFactHandle( 6,
+ object ),
+ null );
+ stack.push( token6 );
+ final Token token3 = new Token( null,
+ new LeapsFactHandle( 3,
+ object ),
+ null );
+ stack.push( token3 );
+ final Token token4 = new Token( null,
+ new LeapsFactHandle( 4,
+ object ),
+ null );
+ stack.push( token4 );
+
+ stack.remove( 1 );
+ assertEquals( token4,
+ stack.peek() );
+ stack.pop();
+ assertEquals( token3,
+ stack.peek() );
+ stack.pop();
+ stack.pop();
+ stack.pop();
+ stack.pop();
+ stack.pop();
+
+ assertTrue( stack.empty() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+ */
+ public void testRemoveTop() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Object object = new Object();
+ final Token token1 = new Token( null,
+ new LeapsFactHandle( 1,
+ object ),
+ null );
+ stack.push( token1 );
+ final Token token2 = new Token( null,
+ new LeapsFactHandle( 2,
+ object ),
+ null );
+ stack.push( token2 );
+ final Token token10 = new Token( null,
+ new LeapsFactHandle( 10,
+ object ),
+ null );
+ stack.push( token10 );
+ final Token token8 = new Token( null,
+ new LeapsFactHandle( 8,
+ object ),
+ null );
+ stack.push( token8 );
+ final Token token6 = new Token( null,
+ new LeapsFactHandle( 6,
+ object ),
+ null );
+ stack.push( token6 );
+ final Token token3 = new Token( null,
+ new LeapsFactHandle( 3,
+ object ),
+ null );
+ stack.push( token3 );
+ final Token token4 = new Token( null,
+ new LeapsFactHandle( 4,
+ object ),
+ null );
+ stack.push( token4 );
+
+ stack.remove( 4 );
+ assertEquals( token3,
+ stack.pop() );
+ assertEquals( token6,
+ stack.pop() );
+ assertEquals( token8,
+ stack.pop() );
+ assertEquals( token10,
+ stack.pop() );
+ assertEquals( token2,
+ stack.pop() );
+ assertEquals( token1,
+ stack.pop() );
+
+ assertTrue( stack.empty() );
+ }
+
+ /*
+ * Test method for 'org.drools.leaps.util.TokenStack.remove(long)'
+ */
+ public void testRemoveMiddle() {
+ final TokenStack stack = new TokenStack();
+ assertTrue( stack.empty() );
+ final Object object = new Object();
+ final Token token1 = new Token( null,
+ new LeapsFactHandle( 1,
+ object ),
+ null );
+ stack.push( token1 );
+ final Token token2 = new Token( null,
+ new LeapsFactHandle( 2,
+ object ),
+ null );
+ stack.push( token2 );
+ final Token token10 = new Token( null,
+ new LeapsFactHandle( 10,
+ object ),
+ null );
+ stack.push( token10 );
+ final Token token8 = new Token( null,
+ new LeapsFactHandle( 8,
+ object ),
+ null );
+ stack.push( token8 );
+ final Token token6 = new Token( null,
+ new LeapsFactHandle( 6,
+ object ),
+ null );
+ stack.push( token6 );
+ final Token token3 = new Token( null,
+ new LeapsFactHandle( 3,
+ object ),
+ null );
+ stack.push( token3 );
+ final Token token4 = new Token( null,
+ new LeapsFactHandle( 4,
+ object ),
+ null );
+ stack.push( token4 );
+
+ stack.remove( 10 );
+ assertEquals( token4,
+ stack.pop() );
+ assertEquals( token3,
+ stack.pop() );
+ assertEquals( token6,
+ stack.pop() );
+ assertEquals( token8,
+ stack.pop() );
+ assertEquals( token2,
+ stack.pop() );
+ assertEquals( token1,
+ stack.pop() );
+
+ assertTrue( stack.empty() );
+ }
+
+}
More information about the jboss-svn-commits
mailing list