/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.core.phreak; import org.drools.core.common.BetaConstraints; import org.drools.core.common.InternalFactHandle; import org.drools.core.common.InternalWorkingMemory; import org.drools.core.reteoo.LeftTuple; import org.drools.core.reteoo.LeftTupleSinkNode; import org.drools.core.reteoo.ReactiveFromNode; import org.drools.core.reteoo.ReactiveFromNodeLeftTuple; import org.drools.core.reteoo.RightTupleImpl; import org.drools.core.rule.ContextEntry; import org.drools.core.spi.PropagationContext; import org.drools.core.spi.Tuple; import java.util.Collection; import static org.drools.core.phreak.PhreakFromNode.*; public class ReactiveObjectUtil { public enum ModificationType { NONE, MODIFY, ADD, REMOVE } public static void notifyModification(ReactiveObject reactiveObject) { notifyModification( reactiveObject, reactiveObject.getLeftTuples(), ModificationType.MODIFY); } public static void notifyModification( Object object, Collection<Tuple> leftTuples, ModificationType type ) { for (Tuple leftTuple : leftTuples) { if (!( (ReactiveFromNodeLeftTuple) leftTuple ).updateModificationState( object, type )) { continue; } PropagationContext propagationContext = leftTuple.getPropagationContext(); ReactiveFromNode node = (ReactiveFromNode)leftTuple.getTupleSink(); LeftTupleSinkNode sink = node.getSinkPropagator().getFirstLeftTupleSink(); InternalWorkingMemory wm = getInternalWorkingMemory(propagationContext); wm.addPropagation(new ReactivePropagation(object, (ReactiveFromNodeLeftTuple)leftTuple, propagationContext, node, sink, type)); } } private static InternalWorkingMemory getInternalWorkingMemory(PropagationContext propagationContext) { InternalFactHandle fh = propagationContext.getFactHandle(); return fh.getEntryPoint().getInternalWorkingMemory(); } static class ReactivePropagation extends PropagationEntry.AbstractPropagationEntry { private final Object object; private final ReactiveFromNodeLeftTuple leftTuple; private final PropagationContext propagationContext; private final ReactiveFromNode node; private final LeftTupleSinkNode sink; private final ModificationType type; ReactivePropagation( Object object, ReactiveFromNodeLeftTuple leftTuple, PropagationContext propagationContext, ReactiveFromNode node, LeftTupleSinkNode sink, ModificationType type ) { this.object = object; this.leftTuple = leftTuple; this.propagationContext = propagationContext; this.node = node; this.sink = sink; this.type = type; } @Override public void execute( InternalWorkingMemory wm ) { if ( leftTuple.resetModificationState( object ) == ModificationType.NONE ) { return; } ReactiveFromNode.ReactiveFromMemory mem = wm.getNodeMemory(node); InternalFactHandle factHandle = node.createFactHandle( leftTuple, propagationContext, wm, object ); if ( type != ModificationType.REMOVE && isAllowed( factHandle, node.getAlphaConstraints(), wm, mem ) ) { ContextEntry[] context = mem.getBetaMemory().getContext(); BetaConstraints betaConstraints = node.getBetaConstraints(); betaConstraints.updateFromTuple( context, wm, leftTuple ); propagate( sink, leftTuple, new RightTupleImpl( factHandle ), betaConstraints, propagationContext, context, RuleNetworkEvaluator.useLeftMemory( node, leftTuple ), mem.getStagedLeftTuples(), null ); } else { LeftTuple childLeftTuple = ((LeftTuple)leftTuple).getFirstChild(); while (childLeftTuple != null) { LeftTuple next = childLeftTuple.getHandleNext(); if ( object == childLeftTuple.getFactHandle().getObject() ) { deleteChildLeftTuple( propagationContext, mem.getStagedLeftTuples(), null, childLeftTuple ); } childLeftTuple = next; } } mem.getBetaMemory().setNodeDirty(wm); } } }