public LeftTuple propagateModifyChildLeftTuple( LeftTuple childLeftTuple, LeftTuple parentLeftTuple, PropagationContext context, InternalWorkingMemory workingMemory, boolean tupleMemoryEnabled) { // iterate to find all child tuples for the shared node while (childLeftTuple != null && childLeftTuple.getLeftParent() == parentLeftTuple) { // this will iterate for each child node when the // the current node is shared // preserve the current LeftTuple, as we need to iterate to the next before re-adding LeftTuple temp = childLeftTuple; childLeftTuple.getLeftTupleSink().modifyLeftTuple(childLeftTuple, context, workingMemory); childLeftTuple = childLeftTuple.getRightParentNext(); temp.reAddLeft(); } return childLeftTuple; }
public void modifyRightTuple( RightTuple rightTuple, PropagationContext context, InternalWorkingMemory workingMemory) { final AccumulateMemory memory = (AccumulateMemory) workingMemory.getNodeMemory(this); BetaMemory bm = memory.betaMemory; // Add and remove to make sure we are in the right bucket and at the end // this is needed to fix for indexing and deterministic iteration bm.getRightTupleMemory().removeAdd(rightTuple); if (bm.getLeftTupleMemory() == null || bm.getLeftTupleMemory().size() == 0) { // do nothing here, as we know there are no left tuples at this stage in sequential mode. return; } LeftTuple childLeftTuple = rightTuple.firstChild; LeftTupleMemory leftMemory = bm.getLeftTupleMemory(); FastIterator leftIt = getLeftIterator(leftMemory); LeftTuple leftTuple = getFirstLeftTuple(rightTuple, leftMemory, context, leftIt); this.constraints.updateFromFactHandle( bm.getContext(), workingMemory, rightTuple.getFactHandle()); // first check our index (for indexed nodes only) hasn't changed and we are returning the same // bucket // We assume a bucket change if leftTuple == null if (childLeftTuple != null && leftMemory.isIndexed() && !leftIt.isFullIterator() && (leftTuple == null || (leftTuple.getMemory() != childLeftTuple.getLeftParent().getMemory()))) { // our index has changed, so delete all the previous matches removePreviousMatchesForRightTuple( rightTuple, context, workingMemory, memory, childLeftTuple); childLeftTuple = null; // null so the next check will attempt matches for new bucket } // if LeftTupleMemory is empty, there are no matches to modify if (leftTuple != null) { if (childLeftTuple == null) { // either we are indexed and changed buckets or // we had no children before, but there is a bucket to potentially match, so try as normal // assert for (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) { if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); // add a new match addMatch(leftTuple, rightTuple, null, null, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } } } } else { // in the same bucket, so iterate and compare for (; leftTuple != null; leftTuple = (LeftTuple) leftIt.next(leftTuple)) { if (this.constraints.isAllowedCachedRight(bm.getContext(), leftTuple)) { final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); LeftTuple temp = null; if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) { temp = childLeftTuple.getRightParentNext(); // we must re-add this to ensure deterministic iteration childLeftTuple.reAddLeft(); removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true); childLeftTuple = temp; } // add a new match addMatch( leftTuple, rightTuple, null, childLeftTuple, workingMemory, memory, accctx, true); if (temp != null) { childLeftTuple = temp; } if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } } else if (childLeftTuple != null && childLeftTuple.getLeftParent() == leftTuple) { LeftTuple temp = childLeftTuple.getRightParentNext(); final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject(); // remove the match removeMatch(rightTuple, childLeftTuple, workingMemory, memory, accctx, true); if (accctx.getAction() == null) { // schedule a test to evaluate the constraints, this is an optimisation for sub // networks // We set Source to LEFT, even though this is a right propagation, because it might // end up // doing multiple right propagations anyway EvaluateResultConstraints action = new EvaluateResultConstraints( ActivitySource.LEFT, leftTuple, context, workingMemory, memory, accctx, true, this); accctx.setAction(action); context.addInsertAction(action); } childLeftTuple = temp; } // else do nothing, was false before and false now. } } } this.constraints.resetFactHandle(bm.getContext()); }