package org.drools.chance.reteoo.nodes;
import org.drools.chance.rule.constraint.ImperfectBetaConstraint;
import org.drools.chance.degree.Degree;
import org.drools.chance.evaluation.Evaluation;
import org.drools.chance.evaluation.SimpleEvaluationImpl;
import org.drools.chance.reteoo.ChanceFactHandle;
import org.drools.chance.reteoo.tuples.*;
import org.drools.common.BetaConstraints;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
import org.drools.core.util.Iterator;
import org.drools.core.util.LinkedList;
import org.drools.core.util.LinkedListEntry;
import org.drools.reteoo.*;
import org.drools.reteoo.builder.BuildContext;
import org.drools.rule.ContextEntry;
import org.drools.spi.BetaNodeFieldConstraint;
import org.drools.spi.PropagationContext;
public class ChanceJoinNode extends JoinNode {
protected int rightSourceId;
protected int leftSourceId;
public ChanceJoinNode(int id, LeftTupleSource leftInput, ObjectSource rightInput, BetaConstraints binder, BuildContext context) {
super( id, leftInput, rightInput, binder, context );
rightSourceId = rightInput instanceof PropagationQueuingNode ? ((PropagationQueuingNode) rightInput).getParentObjectSource().getId() : rightInput.getId();
leftSourceId = leftInput instanceof LeftInputAdapterNode ? ((LeftInputAdapterNode) leftInput).getParentObjectSource().getId() : leftInput.getId();
}
@Override
public RightTuple createRightTuple( InternalFactHandle handle, RightTupleSink sink, PropagationContext context ) {
Evaluation eval = ((ChanceFactHandle) handle).getCachedEvaluation( rightSourceId ) ;
if ( ! this.concurrentRightTupleMemory ) {
if ( context.getActiveWindowTupleList() == null ) {
return new ImperfectRightTuple( handle,
sink,
eval );
} else {
return new ImperfectWindowTuple( handle,
sink,
context.getActiveWindowTupleList(),
eval );
}
} else {
return new ImperfectConcurrentRightTuple( handle,
sink,
eval );
}
}
@Override
public LeftTuple createLeftTuple( LeftTuple leftTuple, RightTuple rightTuple, LeftTuple currentLeftChild, LeftTuple currentRightChild, LeftTupleSink sink, boolean leftTupleMemoryEnabled ) {
ImperfectJoinNodeLeftTuple tup = new ImperfectJoinNodeLeftTuple( leftTuple,
rightTuple,
currentLeftChild,
currentRightChild,
sink,
leftTupleMemoryEnabled);
tup.addEvaluation( ((ImperfectTuple) leftTuple).getEvaluation() );
tup.addEvaluation( ((ImperfectTuple) rightTuple).getEvaluation() );
return tup;
}
@Override
public LeftTuple createLeftTuple( LeftTuple leftTuple, LeftTupleSink sink, boolean leftTupleMemoryEnabled ) {
ImperfectJoinNodeLeftTuple tup = new ImperfectJoinNodeLeftTuple( leftTuple,
sink,
leftTupleMemoryEnabled );
throw new UnsupportedOperationException( " Can't propagate yet " );
}
@Override
public LeftTuple createLeftTuple( InternalFactHandle factHandle, LeftTupleSink sink, boolean leftTupleMemoryEnabled ) {
ImperfectJoinNodeLeftTuple tup = new ImperfectJoinNodeLeftTuple( factHandle,
sink,
leftTupleMemoryEnabled );
Evaluation eval = ((ChanceFactHandle) factHandle).getCachedEvaluation( leftSourceId, true );
tup.addEvaluation( eval );
return tup;
}
@Override
public LeftTuple createLeftTuple( LeftTuple leftTuple, RightTuple rightTuple, LeftTupleSink sink ) {
ImperfectJoinNodeLeftTuple tup = new ImperfectJoinNodeLeftTuple( leftTuple,
rightTuple,
sink);
tup.addEvaluation( ((ImperfectTuple) leftTuple).getEvaluation() );
tup.addEvaluation( ((ImperfectTuple) rightTuple).getEvaluation() );
return tup;
}
@Override
protected void propagateFromRight(RightTuple rightTuple, LeftTuple leftTuple, BetaMemory memory, PropagationContext context, InternalWorkingMemory workingMemory) {
BetaNodeFieldConstraint[] constraintList = this.constraints.getConstraints();
for ( int j = 0; j < constraintList.length; j++ ) {
Degree degree;
BetaNodeFieldConstraint con = constraintList[j];
if ( con instanceof ImperfectBetaConstraint ) {
ImperfectBetaConstraint ibc = (ImperfectBetaConstraint) con;
degree = ibc.matchCachedRight( leftTuple, memory.getContext()[j] );
Evaluation eval = new SimpleEvaluationImpl( ibc.getNodeId(), con.toString(), degree, ibc.getLabel() );
((ImperfectRightTuple) rightTuple).addEvaluation( eval );
} else {
boolean allowed = con.isAllowedCachedRight( leftTuple, memory.getContext()[j] );
if ( ! allowed ) {
// System.err.println( "Crisp beta constraint blocked propagation on ChanceJoinNode propagateFromRight ");
return;
}
}
}
this.sink.propagateAssertLeftTuple( leftTuple,
rightTuple,
null,
null,
context,
workingMemory,
true );
}
protected LeftTuple propagateOrModifyFromRight( RightTuple rightTuple, LeftTuple leftTuple, LeftTuple childLeftTuple, BetaMemory memory, PropagationContext context, InternalWorkingMemory workingMemory ) {
BetaNodeFieldConstraint[] constraintList = this.constraints.getConstraints();
boolean allowed = true;
for ( int j = 0; j < constraintList.length; j++ ) {
Degree degree;
BetaNodeFieldConstraint con = constraintList[j];
if ( con instanceof ImperfectBetaConstraint ) {
ImperfectBetaConstraint ibc = (ImperfectBetaConstraint) con;
degree = ibc.matchCachedRight( leftTuple, memory.getContext()[j] );
Evaluation eval = new SimpleEvaluationImpl( ibc.getNodeId(), con.toString(), degree, ibc.getLabel() );
((ImperfectRightTuple) rightTuple).addEvaluation( eval );
} else {
allowed = ((BetaNodeFieldConstraint) con).isAllowedCachedRight( leftTuple, memory.getContext()[j] );
}
}
if ( allowed ) {
if ( childLeftTuple == null || childLeftTuple.getLeftParent() != leftTuple ) {
this.sink.propagateAssertLeftTuple( leftTuple,
rightTuple,
null,
childLeftTuple,
context,
workingMemory,
true );
} else {
childLeftTuple = this.sink.propagateModifyChildLeftTuple( childLeftTuple,
leftTuple,
context,
workingMemory,
true );
}
} else if ( childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple ) {
childLeftTuple = this.sink.propagateRetractChildLeftTuple( childLeftTuple,
leftTuple,
context,
workingMemory );
}
return childLeftTuple;
}
@Override
protected void propagateFromLeft(RightTuple rightTuple, LeftTuple leftTuple, ContextEntry[] contextEntry, boolean useLeftMemory, PropagationContext context, InternalWorkingMemory workingMemory) {
BetaNodeFieldConstraint[] constraintList = this.constraints.getConstraints();
for ( int j = 0; j < constraintList.length; j++ ) {
Degree degree;
BetaNodeFieldConstraint con = constraintList[j];
if ( con instanceof ImperfectBetaConstraint ) {
ImperfectBetaConstraint ibc = (ImperfectBetaConstraint) con;
degree = ibc.matchCachedLeft( contextEntry[j], rightTuple.getFactHandle() );
Evaluation eval = new SimpleEvaluationImpl( ibc.getNodeId(), con.toString(), degree, ibc.getLabel() );
((ImperfectRightTuple) rightTuple).addEvaluation( eval );
} else {
boolean allowed = ((BetaNodeFieldConstraint) con).isAllowedCachedLeft( contextEntry[j], rightTuple.getFactHandle() );
if ( ! allowed ) {
// System.err.println( "Crisp beta constraint blocked propagation on ChanceJoinNode propagateFromLeft ");
return;
}
}
}
this.sink.propagateAssertLeftTuple( leftTuple,
rightTuple,
null,
null,
context,
workingMemory,
useLeftMemory );
}
@Override
protected LeftTuple propagateOrModifyFromLeft(RightTuple rightTuple, LeftTuple leftTuple, LeftTuple childLeftTuple, ContextEntry[] contextEntry, PropagationContext context, InternalWorkingMemory workingMemory) {
BetaNodeFieldConstraint[] constraintList = this.constraints.getConstraints();
boolean allowed = true;
for ( int j = 0; j < constraintList.length; j++ ) {
Degree degree;
BetaNodeFieldConstraint con = constraintList[j];
if ( con instanceof ImperfectBetaConstraint ) {
ImperfectBetaConstraint ibc = (ImperfectBetaConstraint) con;
degree = ibc.matchCachedRight( leftTuple, contextEntry[j] );
Evaluation eval = new SimpleEvaluationImpl( ibc.getNodeId(), con.toString(), degree, ibc.getLabel() );
((ImperfectRightTuple) rightTuple).addEvaluation( eval );
} else {
allowed = ((BetaNodeFieldConstraint) con).isAllowedCachedRight( leftTuple, contextEntry[j] );
}
}
if ( allowed ) {
if ( childLeftTuple == null || childLeftTuple.getLeftParent() != leftTuple || childLeftTuple.getFirstChild() == null ) {
this.sink.propagateAssertLeftTuple( leftTuple,
rightTuple,
null,
childLeftTuple,
context,
workingMemory,
true );
} else {
childLeftTuple = this.sink.propagateModifyChildLeftTuple( childLeftTuple,
leftTuple,
context,
workingMemory,
true );
}
} else if ( childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple ) {
childLeftTuple = this.sink.propagateRetractChildLeftTuple( childLeftTuple,
leftTuple,
context,
workingMemory );
}
return childLeftTuple;
}
}