Package org.drools.reteoo.nodes

Source Code of org.drools.reteoo.nodes.ReteConditionalBranchNode

package org.drools.reteoo.nodes;

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.PropagationContextFactory;
import org.drools.core.reteoo.ConditionalBranchEvaluator;
import org.drools.core.reteoo.ConditionalBranchEvaluator.ConditionalExecution;
import org.drools.core.reteoo.ConditionalBranchNode;
import org.drools.core.reteoo.LeftTuple;
import org.drools.core.reteoo.LeftTupleSink;
import org.drools.core.reteoo.LeftTupleSource;
import org.drools.core.reteoo.LeftTupleSourceUtils;
import org.drools.core.reteoo.ModifyPreviousTuples;
import org.drools.core.reteoo.ReteooBuilder;
import org.drools.core.reteoo.RightTuple;
import org.drools.core.reteoo.RuleRemovalContext;
import org.drools.core.reteoo.builder.BuildContext;
import org.drools.core.spi.PropagationContext;
import org.drools.core.util.Iterator;

public class ReteConditionalBranchNode extends ConditionalBranchNode {

    public ReteConditionalBranchNode() {
    }

    public ReteConditionalBranchNode(int id, LeftTupleSource tupleSource, ConditionalBranchEvaluator branchEvaluator, BuildContext context) {
        super(id, tupleSource, branchEvaluator, context);
    }

    public void modifyLeftTuple(InternalFactHandle factHandle,
                                ModifyPreviousTuples modifyPreviousTuples,
                                PropagationContext context,
                                InternalWorkingMemory workingMemory) {
        LeftTupleSourceUtils.doModifyLeftTuple(factHandle, modifyPreviousTuples, context, workingMemory,
                                               (LeftTupleSink) this, getLeftInputOtnId(), getLeftInferredMask());
    }

    public void attach( BuildContext context ) {
        super.attach( context );
        if (context == null) {
            return;
        }

        for ( InternalWorkingMemory workingMemory : context.getWorkingMemories() ) {
            PropagationContextFactory pctxFactory = workingMemory.getKnowledgeBase().getConfiguration().getComponentFactory().getPropagationContextFactory();
            final PropagationContext propagationContext = pctxFactory.createPropagationContext(workingMemory.getNextPropagationIdCounter(), PropagationContext.RULE_ADDITION,
                                                                                               null, null, null);
            getLeftTupleSource().updateSink(this, propagationContext, workingMemory);
        }
    }


    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 );
            }
        }
    }

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

        for ( LeftTuple leftTuple =  it.next(); leftTuple != null; 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 );
            }
            getLeftTupleSource().removeTupleSink(this);
        } else {
            throw new RuntimeException("ConditionalBranchNode cannot be shared");
        }
    }

}
TOP

Related Classes of org.drools.reteoo.nodes.ReteConditionalBranchNode

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.