[jboss-svn-commits] JBL Code SVN: r8841 - in labs/jbossrules/trunk/drools-core/src/main/java/org/drools: reteoo and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jan 12 13:06:21 EST 2007
Author: tirelli
Date: 2007-01-12 13:06:12 -0500 (Fri, 12 Jan 2007)
New Revision: 8841
Added:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TupleStartEqualsConstraint.java
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Tuple.java
Log:
JBRULES-218: ReteooBuilder is now complete. Still need to fix tests
Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TupleStartEqualsConstraint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TupleStartEqualsConstraint.java 2007-01-12 17:53:17 UTC (rev 8840)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TupleStartEqualsConstraint.java 2007-01-12 18:06:12 UTC (rev 8841)
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2006 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.
+ */
+
+package org.drools.common;
+
+import org.drools.reteoo.ReteTuple;
+import org.drools.rule.ContextEntry;
+import org.drools.rule.Declaration;
+import org.drools.spi.BetaNodeFieldConstraint;
+
+/**
+ * Checks if one tuple is the start subtuple of other tuple.
+ * For instance, if we have two tuples:
+ *
+ * T1 = [ a, b, c ]
+ * T2 = [ a, b, c, d, e]
+ *
+ * This constraint will evaluate to true as T1 is the starting subtuple
+ * of T2. On the other hand, if we have:
+ *
+ * T1 = [ a, c, b ]
+ * T2 = [ a, b, c, d, e ]
+ *
+ * This constraint will evaluate to false, as T1 is not the starting subtuple
+ * of T2. Besides having the same elements, the order is different.
+ *
+ * This constraint is used when joining subnetworks back into the main
+ * network.
+ *
+ * @author etirelli
+ *
+ */
+public class TupleStartEqualsConstraint
+ implements
+ BetaNodeFieldConstraint {
+
+ private static final long serialVersionUID = 7766998673828986129L;
+
+ private final Declaration[] declarations = new Declaration[0];
+
+ private static final TupleStartEqualsConstraint INSTANCE = new TupleStartEqualsConstraint();
+
+ // this is a stateless constraint, so we can make it a singleton
+ private TupleStartEqualsConstraint() {
+ }
+
+ public static TupleStartEqualsConstraint getInstance() {
+ return INSTANCE;
+ }
+
+ public Declaration[] getRequiredDeclarations() {
+ return this.declarations;
+ }
+
+ public ContextEntry getContextEntry() {
+ return new TupleStartEqualsConstraintContextEntry();
+ }
+
+ public boolean isAllowedCachedLeft(final ContextEntry context,
+ final Object object) {
+ // object MUST be a ReteTuple
+ ReteTuple tuple = ((ReteTuple)object).getSubTuple( ((TupleStartEqualsConstraintContextEntry) context).compareSize );
+ return ((TupleStartEqualsConstraintContextEntry) context).left.equals( tuple );
+ }
+
+ public boolean isAllowedCachedRight(final ReteTuple tuple,
+ final ContextEntry context) {
+ return tuple.equals(((TupleStartEqualsConstraintContextEntry) context).right);
+ }
+
+ public String toString() {
+ return "[ TupleStartEqualsConstraint ]";
+ }
+
+ public int hashCode() {
+ return 10;
+ }
+
+ public boolean equals(final Object object) {
+ if ( this.getClass() == object.getClass() ) {
+ return true;
+ }
+ return false;
+ }
+
+ public static class TupleStartEqualsConstraintContextEntry
+ implements
+ ContextEntry {
+
+ private static final long serialVersionUID = 5841221599619051196L;
+
+ public ReteTuple left;
+ public ReteTuple right;
+
+ // the size of the tuple to compare
+ public int compareSize;
+
+ private ContextEntry entry;
+
+ public TupleStartEqualsConstraintContextEntry() {
+ }
+
+ public ContextEntry getNext() {
+ return this.entry;
+ }
+
+ public void setNext(final ContextEntry entry) {
+ this.entry = entry;
+ }
+
+ public void updateFromTuple(final InternalWorkingMemory workingMemory, final ReteTuple tuple) {
+ this.left = tuple;
+ this.compareSize = tuple.size();
+ }
+
+ public void updateFromFactHandle(final InternalWorkingMemory workingMemory, final InternalFactHandle handle) {
+ // if it is not a rete tuple, then there is a bug in the engine...
+ // it MUST be a rete tuple
+ this.right = ((ReteTuple) handle.getObject()).getSubTuple( this.compareSize );
+ }
+ }
+}
Property changes on: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/TupleStartEqualsConstraint.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ id author date revision
Name: svn:eol-style
+ native
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java 2007-01-12 17:53:17 UTC (rev 8840)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteTuple.java 2007-01-12 18:06:12 UTC (rev 8841)
@@ -179,4 +179,35 @@
// we know the object is never null and always of the type ReteTuple
return equals( (ReteTuple) object );
}
+
+ public int size() {
+ return this.index+1;
+ }
+
+ /**
+ * Returns the ReteTuple that contains the "elements"
+ * first elements in this tuple.
+ *
+ * Use carefully as no cloning is made during this process.
+ *
+ * This method is used by TupleStartEqualsConstraint when
+ * joining a subnetwork tuple into the main network tuple;
+ *
+ * @param elements the number of elements to return, starting from
+ * the begining of the tuple
+ *
+ * @return a ReteTuple containing the "elements" first elements
+ * of this tuple or null if "elements" is greater than size;
+ */
+ public ReteTuple getSubTuple( int elements ) {
+ ReteTuple entry = this;
+ if( elements > this.size() ) {
+ int lastindex = elements-1;
+
+ while ( entry.index != lastindex ) {
+ entry = entry.parent;
+ }
+ }
+ return entry;
+ }
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java 2007-01-12 17:53:17 UTC (rev 8840)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/RightInputAdapterNode.java 2007-01-12 18:06:12 UTC (rev 8841)
@@ -16,54 +16,62 @@
* limitations under the License.
*/
+import org.drools.RuleBaseConfiguration;
import org.drools.common.BaseNode;
+import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
-import org.drools.rule.Column;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
import org.drools.spi.PropagationContext;
+import org.drools.util.Iterator;
+import org.drools.util.ObjectHashMap;
+import org.drools.util.ObjectHashMap.ObjectEntry;
/**
- * When joining two <code>Not<code>s together the resulting <code>Tuple</code> from the first Not
- * Must be adapted to <code>FActHandleImpl</code> so it can be propagated into the second not
+ * When joining a subnetwork into the main network again, RightInputAdapterNode adapts the
+ * subnetwork's tuple into a fact in order right join it with the tuple being propagated in
+ * the main network.
*
* @author <a href="mailto:mark.proctor at jboss.com">Mark Proctor</a>
* @author <a href="mailto:bob at werken.com">Bob McWhirter</a>
+ * @author <a href="mailto:etirelli at redhat.com">Edson Tirelli</a>
*
*/
public class RightInputAdapterNode extends ObjectSource
implements
- TupleSink {
- /**
- *
- */
+ TupleSink,
+ NodeMemory {
+
private static final long serialVersionUID = 320L;
private final TupleSource tupleSource;
- private final Column column;
-
/**
* Constructor specifying the unique id of the node in the Rete network, the position of the propagating <code>FactHandleImpl</code> in
* <code>ReteTuple</code> and the source that propagates the receive <code>ReteTuple<code>s.
*
* @param id
* Unique id
- * @param column
- * The column which specifis the position of the <code>FactHandleImpl</code> in the <code>ReteTuple</code>
* @param source
* The <code>TupleSource</code> which propagates the received <code>ReteTuple</code>
*/
public RightInputAdapterNode(final int id,
- final Column column,
final TupleSource source) {
-
super( id );
- this.column = column;
this.tupleSource = source;
+ this.setHasMemory( true );
}
/**
- * Takes the asserted <code>ReteTuple</code> received from the <code>TupleSource</code> and extract and propagate
- * its <code>FactHandleImpl</code> based on the column specified by te node.
+ * Creates and return the node memory
+ */
+ public Object createMemory(RuleBaseConfiguration config) {
+ return new ObjectHashMap();
+ }
+
+ /**
+ * Takes the asserted <code>ReteTuple</code> received from the <code>TupleSource</code> and
+ * adapts it into a FactHandleImpl
*
* @param tuple
* The asserted <code>ReteTuple</code>.
@@ -75,45 +83,77 @@
public void assertTuple(final ReteTuple tuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
- this.sink.propagateAssertObject( tuple.get( this.column.getOffset() ),
+
+ ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+
+ // creating a dummy fact handle to wrap the tuple
+ final InternalFactHandle handle = workingMemory.getFactHandleFactory().newFactHandle( tuple );
+ // add it to a memory mapping
+ memory.put( tuple,
+ handle );
+
+ // propagate it
+ this.sink.propagateAssertObject( handle,
context,
workingMemory );
}
- /* (non-Javadoc)
- * @see org.drools.reteoo.RetractionCallback#retractTuple(org.drools.reteoo.ReteTuple, org.drools.spi.PropagationContext, org.drools.reteoo.WorkingMemoryImpl)
+ /**
+ * Retracts the corresponding tuple by retrieving and retracting
+ * the fact created for it
*/
public void retractTuple(final ReteTuple tuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
- this.sink.propagateRetractObject( tuple.get( this.column.getOffset() ),
+
+ ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+
+ // retrieve handle from memory
+ final InternalFactHandle handle = (InternalFactHandle) memory.remove( tuple );
+
+ // propagate a retract for it
+ this.sink.propagateRetractObject( handle,
context,
workingMemory,
true );
+
+ // destroy dummy handle
+ workingMemory.getFactHandleFactory().destroyFactHandle( handle );
}
- /* (non-Javadoc)
- * @see org.drools.reteoo.BaseNode#attach()
- */
public void attach() {
this.tupleSource.addTupleSink( this );
}
public void attach(final InternalWorkingMemory[] workingMemories) {
attach();
- // this node has no memory, no point requesting repropagation
+
+ for ( int i = 0, length = workingMemories.length; i < length; i++ ) {
+ final InternalWorkingMemory workingMemory = workingMemories[i];
+ final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
+ PropagationContext.RULE_ADDITION,
+ null,
+ null );
+ this.tupleSource.updateSink( this,
+ propagationContext,
+ workingMemory );
+ }
}
- /* (non-Javadoc)
- * @see org.drools.reteoo.BaseNode#updateNewNode(org.drools.reteoo.WorkingMemoryImpl, org.drools.spi.PropagationContext)
- */
public void updateSink(final ObjectSink sink,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
- this.tupleSource.updateSink( new TupleSinkAdapter( sink,
- this.column.getOffset() ),
- context,
- workingMemory );
+
+ final ObjectHashMap memory = (ObjectHashMap) workingMemory.getNodeMemory( this );
+
+ final Iterator it = memory.iterator();
+
+ // iterates over all propagated handles and assert them to the new sink
+ for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+ sink.assertObject( (InternalFactHandle) entry.getValue(),
+ context,
+ workingMemory );
+ }
}
public void remove(final BaseNode node,
@@ -126,44 +166,4 @@
workingMemories );
}
- /**
- * Used with the updateSink method, so that the parent ObjectSource
- * can update the TupleSink
- * @author mproctor
- *
- */
- private static class TupleSinkAdapter
- implements
- TupleSink {
-
- private static final long serialVersionUID = 1636299857108066554L;
- private ObjectSink sink;
- private int column;
-
- public TupleSinkAdapter(final ObjectSink sink,
- final int column) {
- this.sink = sink;
- this.column = column;
- }
-
- public void assertTuple(final ReteTuple tuple,
- final PropagationContext context,
- final InternalWorkingMemory workingMemory) {
- this.sink.assertObject( tuple.get( this.column ),
- context,
- workingMemory );
- }
-
- public void modifyTuple(final ReteTuple tuple,
- final PropagationContext context,
- final InternalWorkingMemory workingMemory) {
- throw new UnsupportedOperationException( "TupleSinkAdapter onlys supports assertObject method calls" );
- }
-
- public void retractTuple(final ReteTuple tuple,
- final PropagationContext context,
- final InternalWorkingMemory workingMemory) {
- throw new UnsupportedOperationException( "TupleSinkAdapter onlys supports assertObject method calls" );
- }
- }
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java 2007-01-12 17:53:17 UTC (rev 8840)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/GroupElementBuilder.java 2007-01-12 18:06:12 UTC (rev 8841)
@@ -16,15 +16,20 @@
package org.drools.reteoo.builder;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.drools.RuntimeDroolsException;
+import org.drools.common.TupleStartEqualsConstraint;
import org.drools.reteoo.ExistsNode;
import org.drools.reteoo.JoinNode;
import org.drools.reteoo.LeftInputAdapterNode;
import org.drools.reteoo.NotNode;
+import org.drools.reteoo.ObjectSource;
+import org.drools.reteoo.RightInputAdapterNode;
import org.drools.reteoo.TupleSource;
import org.drools.rule.Column;
import org.drools.rule.GroupElement;
@@ -53,8 +58,6 @@
/**
* @inheritDoc
- *
- *
*/
public void build(BuildContext context,
BuildUtils utils,
@@ -66,121 +69,19 @@
builder.build( context,
utils,
rce );
-
- // for ( final Iterator it = subrule.getChildren().iterator(); it.hasNext(); ) {
- // final Object object = it.next();
- //
- // if ( object instanceof EvalCondition ) {
- // final EvalCondition eval = (EvalCondition) object;
- // checkUnboundDeclarations( eval.getRequiredDeclarations() );
- // this.tupleSource = attachNode( new EvalConditionNode( this.id++,
- // this.tupleSource,
- // eval ) );
- // continue;
- // }
- //
- // BetaConstraints binder = null;
- // Column column = null;
- //
- // if ( object instanceof Column ) {
- // column = (Column) object;
- //
- // // @REMOVEME after the milestone period
- // if ( (binder != null) && (binder != EmptyBetaConstraints.getInstance()) ) throw new RuntimeDroolsException( "This is a bug! Please report to Drools development team!" );
- //
- // binder = attachColumn( (Column) object,
- // subrule,
- // this.removeIdentities );
- //
- // // If a tupleSource does not exist then we need to adapt this
- // // into
- // // a TupleSource using LeftInputAdapterNode
- // if ( this.tupleSource == null ) {
- // this.tupleSource = attachNode( new LeftInputAdapterNode( this.id++,
- // this.objectSource ) );
- //
- // // objectSource is created by the attachColumn method, if we
- // // adapt this to
- // // a TupleSource then we need to null the objectSource
- // // reference.
- // this.objectSource = null;
- // }
- // } else if ( object instanceof GroupElement ) {
- // // If its not a Column or EvalCondition then it can either be a Not or an Exists
- // GroupElement ce = (GroupElement) object;
- // while ( !(ce.getChildren().get( 0 ) instanceof Column) ) {
- // ce = (GroupElement) ce.getChildren().get( 0 );
- // }
- // column = (Column) ce.getChildren().get( 0 );
- //
- // // If a tupleSource does not exist then we need to adapt an
- // // InitialFact into a a TupleSource using LeftInputAdapterNode
- // if ( this.tupleSource == null ) {
- // // adjusting offset as all tuples will now contain initial-fact at index 0
- // this.currentOffsetAdjustment = 1;
- //
- // final ObjectSource objectSource = attachNode( new ObjectTypeNode( this.id++,
- // new ClassObjectType( InitialFact.class ),
- // this.rete,
- // this.ruleBase.getConfiguration().getAlphaNodeHashingThreshold() ) );
- //
- // this.tupleSource = attachNode( new LeftInputAdapterNode( this.id++,
- // objectSource ) );
- // }
- //
- // // @REMOVEME after the milestone period
- // if ( (binder != null) && (binder != EmptyBetaConstraints.getInstance()) ) throw new RuntimeDroolsException( "This is a bug! Please report to Drools development team!" );
- //
- // binder = attachColumn( column,
- // subrule,
- // this.removeIdentities );
- // }
- //
- // if ( (object instanceof GroupElement) && (((GroupElement) object).isNot()) ) {
- // attachNot( this.tupleSource,
- // (GroupElement) object,
- // this.objectSource,
- // binder,
- // column );
- // binder = null;
- // } else if ( (object instanceof GroupElement) && (((GroupElement) object).isExists()) ) {
- // attachExists( this.tupleSource,
- // (GroupElement) object,
- // this.objectSource,
- // binder,
- // column );
- // binder = null;
- // } else if ( object.getClass() == From.class ) {
- // attachFrom( this.tupleSource,
- // (From) object );
- // } else if ( object.getClass() == Accumulate.class ) {
- // attachAccumulate( this.tupleSource,
- // subrule,
- // (Accumulate) object );
- // } else if ( object.getClass() == Collect.class ) {
- // attachCollect( this.tupleSource,
- // subrule,
- // (Collect) object );
- // } else if ( this.objectSource != null ) {
- // this.tupleSource = attachNode( new JoinNode( this.id++,
- // this.tupleSource,
- // this.objectSource,
- // binder ) );
- // binder = null;
- // }
- // }
-
}
/**
* @inheritDoc
*/
- public boolean requiresLeftActivation( BuildUtils utils, RuleConditionElement rce ) {
+ public boolean requiresLeftActivation(BuildUtils utils,
+ RuleConditionElement rce) {
GroupElement ge = (GroupElement) rce;
ReteooComponentBuilder builder = (ReteooComponentBuilder) geBuilders.get( ge.getType() );
-
- return builder.requiresLeftActivation( utils, rce );
+
+ return builder.requiresLeftActivation( utils,
+ rce );
}
private static class AndBuilder
@@ -235,19 +136,21 @@
}
}
- public boolean requiresLeftActivation(BuildUtils utils, RuleConditionElement rce) {
+ public boolean requiresLeftActivation(BuildUtils utils,
+ RuleConditionElement rce) {
GroupElement and = (GroupElement) rce;
// need to check this because in the case of an empty rule, the root AND
// will have no child
- if( and.getChildren().isEmpty() ) {
+ if ( and.getChildren().isEmpty() ) {
return true;
- }
-
+ }
+
RuleConditionElement child = (RuleConditionElement) and.getChildren().get( 0 );
ReteooComponentBuilder builder = utils.getBuilderFor( child );
-
- return builder.requiresLeftActivation( utils, child );
+
+ return builder.requiresLeftActivation( utils,
+ child );
}
}
@@ -264,8 +167,9 @@
throw new RuntimeDroolsException( "BUG: Can't build a rete network with an inner OR group element" );
}
- public boolean requiresLeftActivation(BuildUtils utils, RuleConditionElement rce) {
- return false;
+ public boolean requiresLeftActivation(BuildUtils utils,
+ RuleConditionElement rce) {
+ throw new RuntimeDroolsException( "BUG: Can't build a rete network with an inner OR group element" );
}
}
@@ -285,9 +189,10 @@
BuildUtils utils,
RuleConditionElement rce) {
GroupElement not = (GroupElement) rce;
-
- // NOT must save current column index in order to restore it later
+
+ // NOT must save some context info to restore it later
int currentColumnIndex = context.getCurrentColumnOffset();
+ TupleSource tupleSource = context.getTupleSource();
// get child
RuleConditionElement child = (RuleConditionElement) not.getChildren().get( 0 );
@@ -300,21 +205,37 @@
utils,
child );
- // if child is a column
- if ( child instanceof Column ) {
- // then no sub-network needed... just a simple NOT node
- context.setTupleSource( (TupleSource) utils.attachNode( context,
- new NotNode( context.getNextId(),
- context.getTupleSource(),
- context.getObjectSource(),
- context.getBetaconstraints() ) ) );
- context.setBetaconstraints( null );
- context.setObjectSource( null );
+ // if child is not a column adapt it into a subnetwork
+ if ( !(child instanceof Column) ) {
- } else {
- // TODO: otherwise attach subnetwork
+ // attach right input adapter node to convert tuple source into an object source
+ context.setObjectSource( (ObjectSource) utils.attachNode( context,
+ new RightInputAdapterNode( context.getNextId(),
+ context.getTupleSource() ) ) );
+
+ // restore tuple source from before the start of the sub network
+ context.setTupleSource( tupleSource );
+
+ // create a tuple start equals constraint and set it in the context
+ TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+ List predicates = new ArrayList();
+ predicates.add( constraint );
+ context.setBetaconstraints( utils.createBetaNodeConstraint( context,
+ predicates ) );
+
}
-
+
+ // then attach the NOT node. It will work both as a simple not node
+ // or as subnetwork join node as the context was set appropriatelly
+ // in each case
+ context.setTupleSource( (TupleSource) utils.attachNode( context,
+ new NotNode( context.getNextId(),
+ context.getTupleSource(),
+ context.getObjectSource(),
+ context.getBetaconstraints() ) ) );
+ context.setBetaconstraints( null );
+ context.setObjectSource( null );
+
// restore column index
context.setCurrentColumnOffset( currentColumnIndex );
}
@@ -342,8 +263,9 @@
RuleConditionElement rce) {
GroupElement exists = (GroupElement) rce;
- // EXISTS must save current column index in order to restore it later
+ // EXISTS must save some context info to restore it later
int currentColumnIndex = context.getCurrentColumnOffset();
+ TupleSource tupleSource = context.getTupleSource();
// get child
RuleConditionElement child = (RuleConditionElement) exists.getChildren().get( 0 );
@@ -356,21 +278,37 @@
utils,
child );
- // if child is a column
- if ( child instanceof Column ) {
- // then no sub-network needed... just a simple EXISTS node
- context.setTupleSource( (TupleSource) utils.attachNode( context,
- new ExistsNode( context.getNextId(),
- context.getTupleSource(),
- context.getObjectSource(),
- context.getBetaconstraints() ) ) );
- context.setBetaconstraints( null );
- context.setObjectSource( null );
+ // if child is not a column adapt it into a subnetwork
+ if ( !(child instanceof Column) ) {
- } else {
- // TODO: otherwise attach subnetwork
+ // attach right input adapter node to convert tuple source into an object source
+ context.setObjectSource( (ObjectSource) utils.attachNode( context,
+ new RightInputAdapterNode( context.getNextId(),
+ context.getTupleSource() ) ) );
+
+ // restore tuple source from before the start of the sub network
+ context.setTupleSource( tupleSource );
+
+ // create a tuple start equals constraint and set it in the context
+ TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
+ List predicates = new ArrayList();
+ predicates.add( constraint );
+ context.setBetaconstraints( utils.createBetaNodeConstraint( context,
+ predicates ) );
+
}
-
+
+ // then attach the EXISTS node. It will work both as a simple exists node
+ // or as subnetwork join node as the context was set appropriatelly
+ // in each case
+ context.setTupleSource( (TupleSource) utils.attachNode( context,
+ new ExistsNode( context.getNextId(),
+ context.getTupleSource(),
+ context.getObjectSource(),
+ context.getBetaconstraints() ) ) );
+ context.setBetaconstraints( null );
+ context.setObjectSource( null );
+
// restore column index
context.setCurrentColumnOffset( currentColumnIndex );
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Tuple.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Tuple.java 2007-01-12 17:53:17 UTC (rev 8840)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/spi/Tuple.java 2007-01-12 18:06:12 UTC (rev 8841)
@@ -57,6 +57,16 @@
InternalFactHandle[] getFactHandles();
+ /**
+ * Returns the tuple recency
+ * @return
+ */
long getRecency();
+
+ /**
+ * Returns the size of this tuple in number of elements (columns)
+ * @return
+ */
+ int size();
}
\ No newline at end of file
More information about the jboss-svn-commits
mailing list