Package org.drools.core.reteoo

Source Code of org.drools.core.reteoo.ConditionalBranchNode$ConditionalBranchMemory

package org.drools.core.reteoo;

import org.drools.core.RuleBaseConfiguration;
import org.drools.core.base.DroolsQuery;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.LeftTupleIterator;
import org.drools.core.common.Memory;
import org.drools.core.common.MemoryFactory;
import org.drools.core.common.PropagationContextImpl;
import org.drools.core.common.UpdateContext;
import org.drools.core.util.AbstractBaseLinkedListNode;
import org.drools.core.reteoo.builder.BuildContext;
import org.drools.core.reteoo.ConditionalBranchEvaluator.ConditionalExecution;
import org.drools.core.spi.PropagationContext;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

/**
* Node which allows to follow different paths in the Rete-OO network,
* based on the result of a boolean <code>Test</code>.
*/
public class ConditionalBranchNode extends LeftTupleSource implements LeftTupleSinkNode, MemoryFactory  {

    private LeftTupleSource tupleSource;

    private ConditionalBranchEvaluator branchEvaluator;

    protected boolean tupleMemoryEnabled;

    private LeftTupleSinkNode previousTupleSinkNode;
    private LeftTupleSinkNode nextTupleSinkNode;

    public ConditionalBranchNode() { }

    public ConditionalBranchNode( int id,
                                  LeftTupleSource tupleSource,
                                  ConditionalBranchEvaluator branchEvaluator,
                                  BuildContext context ) {
        super( id,
               context.getPartitionId(),
               context.getRuleBase().getConfiguration().isMultithreadEvaluation());
        this.tupleSource = tupleSource;
        this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
        this.branchEvaluator = branchEvaluator;

        initMasks(context, tupleSource);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        super.readExternal(in);
        tupleSource = (LeftTupleSource) in.readObject();
        tupleMemoryEnabled = in.readBoolean();
        branchEvaluator = (ConditionalBranchEvaluator) in.readObject();
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        super.writeExternal(out);
        out.writeObject(tupleSource);
        out.writeBoolean(tupleMemoryEnabled);
        out.writeObject(branchEvaluator);
    }
   

    public ConditionalBranchEvaluator getBranchEvaluator() {
        return branchEvaluator;
    }

    public void attach( BuildContext context ) {
        this.tupleSource.addTupleSink(this, context);
        if (context == null) {
            return;
        }

        for ( InternalWorkingMemory workingMemory : context.getWorkingMemories() ) {
            final PropagationContext propagationContext = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
                                                                                      PropagationContext.RULE_ADDITION,
                                                                                      null,
                                                                                      null,
                                                                                      null );
            this.tupleSource.updateSink( this,
                                         propagationContext,
                                         workingMemory );
        }
    }

    public void networkUpdated(UpdateContext updateContext) {
        this.tupleSource.networkUpdated(updateContext);
    }

    public LeftTupleSource getLeftTupleSource() {
        return this.tupleSource;
    }

    public void assertLeftTuple(final LeftTuple leftTuple,
                                final PropagationContext context,
                                final InternalWorkingMemory workingMemory) {
        final ConditionalBranchMemory memory = (ConditionalBranchMemory) workingMemory.getNodeMemory( this );

        boolean breaking = false;
        ConditionalExecution conditionalExecution = branchEvaluator.evaluate( leftTuple, workingMemory, memory.context );

        if ( conditionalExecution != null ) {
            boolean useLeftMemory = true;
            if ( !this.tupleMemoryEnabled ) {
                // This is a hack, to not add closed DroolsQuery objects
                Object object = leftTuple.get( 0 ).getObject();
                if ( !(object instanceof DroolsQuery) || !((DroolsQuery) object).isOpen() ) {
                    useLeftMemory = false;
                }
            }

            conditionalExecution.getSink().propagateAssertLeftTuple( leftTuple,
                                                                     context,
                                                                     workingMemory,
                                                                     useLeftMemory );
            breaking = conditionalExecution.isBreaking();
        }

        if ( !breaking ) {
            this.sink.propagateAssertLeftTuple( leftTuple,
                                                context,
                                                workingMemory,
                                                this.tupleMemoryEnabled );
        }
    }

    public void retractLeftTuple(final LeftTuple leftTuple,
                                 final PropagationContext context,
                                 final InternalWorkingMemory workingMemory) {
        if ( leftTuple.getFirstChild() != null ) {
            this.sink.propagateRetractLeftTuple( leftTuple,
                                                 context,
                                                 workingMemory );
        }
    }

    public void modifyLeftTuple(LeftTuple leftTuple,
                                PropagationContext context,
                                InternalWorkingMemory workingMemory) {
        final ConditionalBranchMemory memory = (ConditionalBranchMemory) workingMemory.getNodeMemory( this );
        boolean wasPropagated = leftTuple.getFirstChild() != null;

        ConditionalExecution conditionalExecution = branchEvaluator.evaluate( leftTuple, workingMemory, memory.context );

        if ( wasPropagated ) {
            LeftTupleSink mainSink = this.sink.getSinks()[0];
            LeftTupleSink oldSink = leftTuple.getFirstChild().getSink();

            if ( conditionalExecution != null ) {
                LeftTupleSink newSink = conditionalExecution.getSink().getSinks()[0];
                if ( oldSink.equals(newSink) ) {
                    // old and new propagation on the same branch sink -> modify
                    conditionalExecution.getSink().propagateModifyChildLeftTuple( leftTuple,
                                                                                  context,
                                                                                  workingMemory,
                                                                                  this.tupleMemoryEnabled );
                    if ( !conditionalExecution.isBreaking() ) {
                        this.sink.propagateAssertLeftTuple( leftTuple,
                                                            context,
                                                            workingMemory,
                                                            this.tupleMemoryEnabled );
                    }
                } else {
                    if ( oldSink.equals(mainSink) ) {
                        // old propagation on main sink
                        if ( conditionalExecution.isBreaking() ) {
                            // condition is breaking -> retract on main
                            this.sink.propagateRetractLeftTuple( leftTuple,
                                                                 context,
                                                                 workingMemory );
                        } else {
                            // condition not breaking -> also modify main
                            this.sink.propagateModifyChildLeftTuple( leftTuple,
                                                                     context,
                                                                     workingMemory,
                                                                     this.tupleMemoryEnabled );
                        }
                    } else {
                        // old propagation on branch sink -> retract
                        conditionalExecution.getSink().propagateRetractLeftTuple( leftTuple,
                                                                                  context,
                                                                                  workingMemory );
                   }

                    // new propagation on different branch sink -> assert
                    conditionalExecution.getSink().propagateAssertLeftTuple( leftTuple,
                                                                             context,
                                                                             workingMemory,
                                                                             this.tupleMemoryEnabled );
                    if ( !conditionalExecution.isBreaking() && !oldSink.equals(mainSink) ) {
                        this.sink.propagateAssertLeftTuple( leftTuple,
                                                            context,
                                                            workingMemory,
                                                            this.tupleMemoryEnabled );
                    }
                }
            } else {
                if ( oldSink.equals(mainSink) ) {
                    // old and new propagation on main sink -> modify
                    this.sink.propagateModifyChildLeftTuple( leftTuple,
                                                             context,
                                                             workingMemory,
                                                             this.tupleMemoryEnabled );
                } else {
                    // old propagation on branch sink -> retract
                    this.sink.propagateRetractLeftTuple( leftTuple,
                                                         context,
                                                         workingMemory );
                    // new propagation on main sink -> assert
                    this.sink.propagateAssertLeftTuple( leftTuple,
                                                        context,
                                                        workingMemory,
                                                        this.tupleMemoryEnabled );
                }
            }
        } else {
            // not propagated -> assert
            boolean breaking = false;
            if ( conditionalExecution != null ) {
                conditionalExecution.getSink().propagateAssertLeftTuple( leftTuple,
                                                                         context,
                                                                         workingMemory,
                                                                         this.tupleMemoryEnabled );
                breaking = conditionalExecution.isBreaking();
            }
            if ( !breaking ) {
                this.sink.propagateAssertLeftTuple( leftTuple,
                                                    context,
                                                    workingMemory,
                                                    this.tupleMemoryEnabled );
            }
        }
    }

    /**
     * Produce a debug string.
     *
     * @return The debug string.
     */
    public String toString() {
        return "[ConditionalBranchNode: cond=" + this.branchEvaluator + "]";
    }

    public int hashCode() {
        return this.tupleSource.hashCode() ^ this.branchEvaluator.hashCode();
    }

    public boolean equals(final Object object) {
        if ( this == object ) {
            return true;
        }

        if ( object == null || object.getClass() != ConditionalBranchNode.class ) {
            return false;
        }

        final ConditionalBranchNode other = (ConditionalBranchNode) object;

        return this.tupleSource.equals( other.tupleSource ) && this.branchEvaluator.equals( other.branchEvaluator );
    }

    public Memory createMemory(final RuleBaseConfiguration config, InternalWorkingMemory wm) {
        return new ConditionalBranchMemory( branchEvaluator.createContext() );
    }

    @Override
    public LeftTuple createPeer(LeftTuple original) {
        EvalNodeLeftTuple peer = new EvalNodeLeftTuple();
        peer.initPeer( (BaseLeftTuple) original, this );
        original.setPeer( peer );
        return peer;
    }

    public void updateSink(final LeftTupleSink sink,
                           final PropagationContext context,
                           final InternalWorkingMemory workingMemory) {
        LeftTupleIterator it = LeftTupleIterator.iterator( workingMemory, this );

        for ( LeftTuple leftTuple =  ( LeftTuple ) it.next(); leftTuple != null; leftTuple =  ( LeftTuple ) it.next() ) {
            LeftTuple childLeftTuple = leftTuple.getFirstChild();
            while ( childLeftTuple != null ) {
                RightTuple rightParent = childLeftTuple.getRightParent();
                sink.assertLeftTuple( sink.createLeftTuple( leftTuple, rightParent, childLeftTuple, null, sink, true ),
                                      context,
                                      workingMemory );

                while ( childLeftTuple != null && childLeftTuple.getRightParent() == rightParent ) {
                    // skip to the next child that has a different right parent
                    childLeftTuple = childLeftTuple.getLeftParentNext();
                }
            }
        }
    }

    protected void doRemove(final RuleRemovalContext context,
                            final ReteooBuilder builder,
                            final InternalWorkingMemory[] workingMemories) {
        if ( !this.isInUse() ) {
            for( InternalWorkingMemory workingMemory : workingMemories ) {
                workingMemory.clearNodeMemory( this );
            }
            tupleSource.removeTupleSink( this );
        } else {
            throw new RuntimeException("ConditionalBranchNode cannot be shared");
        }
    }

    protected void doCollectAncestors(NodeSet nodeSet) {
        this.tupleSource.collectAncestors(nodeSet);
    }

    public boolean isLeftTupleMemoryEnabled() {
        return tupleMemoryEnabled;
    }

    public void setLeftTupleMemoryEnabled(boolean tupleMemoryEnabled) {
        this.tupleMemoryEnabled = tupleMemoryEnabled;
    }

    /**
     * Returns the next node
     * @return
     *      The next TupleSinkNode
     */
    public LeftTupleSinkNode getNextLeftTupleSinkNode() {
        return this.nextTupleSinkNode;
    }

    /**
     * Sets the next node
     * @param next
     *      The next TupleSinkNode
     */
    public void setNextLeftTupleSinkNode(final LeftTupleSinkNode next) {
        this.nextTupleSinkNode = next;
    }

    /**
     * Returns the previous node
     * @return
     *      The previous TupleSinkNode
     */
    public LeftTupleSinkNode getPreviousLeftTupleSinkNode() {
        return this.previousTupleSinkNode;
    }

    /**
     * Sets the previous node
     * @param previous
     *      The previous TupleSinkNode
     */
    public void setPreviousLeftTupleSinkNode(final LeftTupleSinkNode previous) {
        this.previousTupleSinkNode = previous;
    }

    public short getType() {
        return NodeTypeEnums.ConditionalBranchNode;
    }

    public LeftTuple createLeftTuple(InternalFactHandle factHandle,
                                     LeftTupleSink sink,
                                     boolean leftTupleMemoryEnabled) {
        return new EvalNodeLeftTuple(factHandle, sink, leftTupleMemoryEnabled );
    }

    public LeftTuple createLeftTuple(final InternalFactHandle factHandle,
                                     final LeftTuple leftTuple,
                                     final LeftTupleSink sink) {
        return new EvalNodeLeftTuple(factHandle,leftTuple, sink );
    }

    public LeftTuple createLeftTuple(LeftTuple leftTuple,
                                     LeftTupleSink sink,
                                     PropagationContext pctx, boolean leftTupleMemoryEnabled) {
        return new EvalNodeLeftTuple(leftTuple,sink, pctx, leftTupleMemoryEnabled );
    }

    public LeftTuple createLeftTuple(LeftTuple leftTuple,
                                     RightTuple rightTuple,
                                     LeftTupleSink sink) {
        return new EvalNodeLeftTuple(leftTuple, rightTuple, sink );
    }

    public LeftTuple createLeftTuple(LeftTuple leftTuple,
                                     RightTuple rightTuple,
                                     LeftTuple currentLeftChild,
                                     LeftTuple currentRightChild,
                                     LeftTupleSink sink,
                                     boolean leftTupleMemoryEnabled) {
        return new EvalNodeLeftTuple(leftTuple, rightTuple, currentLeftChild, currentRightChild, sink, leftTupleMemoryEnabled );
    }

    public static class ConditionalBranchMemory extends AbstractBaseLinkedListNode<Memory>
            implements
            Externalizable,
            Memory {

        private static final long serialVersionUID = 510l;

        public Object             context;
       
        private SegmentMemory     segmentMemory;

        public ConditionalBranchMemory() {

        }

        public ConditionalBranchMemory(final Object context) {
            this.context = context;
        }

        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            context = in.readObject();
        }

        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject( context );
        }

        public short getNodeType() {
            return NodeTypeEnums.ConditionalBranchNode;
        }
       
        public void setSegmentMemory(SegmentMemory segmentMemory) {
            this.segmentMemory = segmentMemory;
        }

        public SegmentMemory getSegmentMemory() {
            return segmentMemory;
        }
    }

    protected ObjectTypeNode getObjectTypeNode() {
        return tupleSource.getObjectTypeNode();
    }

}
TOP

Related Classes of org.drools.core.reteoo.ConditionalBranchNode$ConditionalBranchMemory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.