/*
* Copyright 2005 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.reteoo;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.drools.core.FactHandle;
import org.drools.core.QueryResults;
import org.drools.core.SessionConfiguration;
import org.drools.core.base.DroolsQuery;
import org.drools.core.base.InternalViewChangedEventListener;
import org.drools.core.base.NonCloningQueryViewListener;
import org.drools.core.base.QueryRowWithSubruleIndex;
import org.drools.core.base.StandardQueryViewChangedEventListener;
import org.drools.core.common.*;
import org.drools.core.common.TupleStartEqualsConstraint.TupleStartEqualsConstraintContextEntry;
import org.drools.core.util.FastIterator;
import org.drools.core.util.index.RightTupleList;
import org.drools.core.event.AgendaEventSupport;
import org.drools.core.event.WorkingMemoryEventSupport;
import org.drools.core.impl.EnvironmentFactory;
import org.drools.core.impl.StatefulKnowledgeSessionImpl;
import org.drools.core.marshalling.impl.MarshallerReaderContext;
import org.drools.core.marshalling.impl.MarshallerWriteContext;
import org.drools.core.marshalling.impl.PersisterHelper;
import org.drools.core.marshalling.impl.ProtobufMessages;
import org.drools.core.marshalling.impl.ProtobufMessages.ActionQueue.Action;
import org.drools.core.marshalling.impl.ProtobufMessages.ActionQueue.Assert;
import org.drools.core.phreak.RuleNetworkEvaluatorActivation;
import org.drools.core.phreak.SegmentUtilities;
import org.drools.core.reteoo.AccumulateNode.AccumulateContext;
import org.drools.core.reteoo.AccumulateNode.AccumulateMemory;
import org.drools.core.reteoo.AccumulateNode.ActivitySource;
import org.drools.core.reteoo.LeftInputAdapterNode.LiaNodeMemory;
import org.drools.core.rule.Declaration;
import org.drools.core.rule.EntryPoint;
import org.drools.core.rule.Package;
import org.drools.core.rule.Rule;
import org.drools.core.runtime.rule.impl.LiveQueryImpl;
import org.drools.core.runtime.rule.impl.OpenQueryViewChangedEventListenerAdapter;
import org.drools.core.spi.FactHandleFactory;
import org.drools.core.spi.PropagationContext;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.ObjectFilter;
import org.kie.api.runtime.rule.LiveQuery;
import org.kie.api.runtime.rule.ViewChangedEventListener;
/**
* Implementation of <code>WorkingMemory</code>.
*/
public class ReteooWorkingMemory extends AbstractWorkingMemory implements ReteooWorkingMemoryInterface {
public ReteooWorkingMemory() {
super();
}
public ReteooWorkingMemory(final int id,
final InternalRuleBase ruleBase) {
this( id,
ruleBase,
SessionConfiguration.getDefaultInstance(),
EnvironmentFactory.newEnvironment() );
}
/**
* Construct.
*
* @param ruleBase
* The backing rule-base.
*/
public ReteooWorkingMemory(final int id,
final InternalRuleBase ruleBase,
final SessionConfiguration config,
final Environment environment) {
super( id,
ruleBase,
ruleBase.newFactHandleFactory(),
config,
environment );
this.agenda = ruleBase.getConfiguration().getComponentFactory().getAgendaFactory().createAgenda( ruleBase );
this.agenda.setWorkingMemory( this );
}
public ReteooWorkingMemory(final int id,
final InternalRuleBase ruleBase,
final SessionConfiguration config,
final Environment environment,
final WorkingMemoryEventSupport workingMemoryEventSupport,
final AgendaEventSupport agendaEventSupport) {
super( id,
ruleBase,
ruleBase.newFactHandleFactory(),
config,
environment,
workingMemoryEventSupport,
agendaEventSupport );
this.agenda = ruleBase.getConfiguration().getComponentFactory().getAgendaFactory().createAgenda( ruleBase );
this.agenda.setWorkingMemory( this );
}
public ReteooWorkingMemory(final int id,
final InternalRuleBase ruleBase,
final FactHandleFactory handleFactory,
final InternalFactHandle initialFactHandle,
final long propagationContext,
final SessionConfiguration config,
final InternalAgenda agenda,
final Environment environment) {
super( id,
ruleBase,
handleFactory,
initialFactHandle,
//ruleBase.newFactHandleFactory(context),
propagationContext,
config,
environment );
this.agenda = agenda;
this.agenda.setWorkingMemory( this );
// InputPersister.readFactHandles( context );
// super.read( context );
}
public QueryResults getQueryResults(final String query) {
return getQueryResults( query,
null );
}
@SuppressWarnings("unchecked")
public QueryResults getQueryResults(final String queryName,
final Object[] arguments) {
try {
startOperation();
this.ruleBase.readLock();
this.lock.lock();
this.ruleBase.executeQueuedActions();
executeQueuedActions();
DroolsQuery queryObject = new DroolsQuery( queryName,
arguments,
getQueryListenerInstance(),
false ,
null,
null,
null,
null );
InternalFactHandle handle = this.handleFactory.newFactHandle( queryObject,
null,
this,
this );
final PropagationContext pCtx = new PropagationContextImpl( getNextPropagationIdCounter(),
PropagationContext.INSERTION,
null,
null,
handle,
getEntryPoint() );
BaseNode[] tnodes = evalQuery(queryName, queryObject, handle, pCtx);
List<Map<String, Declaration>> decls = new ArrayList<Map<String, Declaration>>();
if ( tnodes != null ) {
for ( BaseNode node : tnodes ) {
decls.add( ((QueryTerminalNode) node).getSubRule().getOuterDeclarations() );
}
}
executeQueuedActions();
this.handleFactory.destroyFactHandle( handle );
return new QueryResults( (List<QueryRowWithSubruleIndex>) queryObject.getQueryResultCollector().getResults(),
decls.toArray( new Map[decls.size()] ),
this,
( queryObject.getQuery() != null ) ? queryObject.getQuery().getParameters() : new Declaration[0] );
} finally {
this.lock.unlock();
this.ruleBase.readUnlock();
endOperation();
}
}
private InternalViewChangedEventListener getQueryListenerInstance() {
switch ( this.config.getQueryListenerOption() ) {
case STANDARD :
return new StandardQueryViewChangedEventListener();
case LIGHTWEIGHT :
return new NonCloningQueryViewListener();
}
return null;
}
public LiveQuery openLiveQuery(final String query,
final Object[] arguments,
final ViewChangedEventListener listener) {
try {
startOperation();
this.ruleBase.readLock();
this.lock.lock();
this.ruleBase.executeQueuedActions();
executeQueuedActions();
DroolsQuery queryObject = new DroolsQuery( query,
arguments,
new OpenQueryViewChangedEventListenerAdapter( listener ),
true,
null,
null,
null,
null );
InternalFactHandle handle = this.handleFactory.newFactHandle( queryObject,
null,
this,
this );
final PropagationContext pCtx = new PropagationContextImpl( getNextPropagationIdCounter(),
PropagationContext.INSERTION,
null,
null,
handle,
getEntryPoint() );
BaseNode[] tnodes = evalQuery(queryObject.getName(), queryObject, handle, pCtx);
executeQueuedActions();
return new LiveQueryImpl( this,
handle );
} finally {
this.lock.unlock();
this.ruleBase.readUnlock();
endOperation();
}
}
private BaseNode[] evalQuery(String queryName, DroolsQuery queryObject, InternalFactHandle handle, PropagationContext pCtx) {
BaseNode[] tnodes = ( BaseNode[] ) ruleBase.getReteooBuilder().getTerminalNodes(queryName);
if ( this.ruleBase.getConfiguration().isPhreakEnabled() ) {
if ( tnodes == null ) {
throw new RuntimeException( "Query '" + queryName + "' does not exist");
}
QueryTerminalNode tnode = ( QueryTerminalNode ) tnodes[0];
LeftTupleSource lts = tnode.getLeftTupleSource();
while ( lts.getType() != NodeTypeEnums.LeftInputAdapterNode ) {
lts = lts.getLeftTupleSource();
}
LeftInputAdapterNode lian = ( LeftInputAdapterNode ) lts;
LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory( (MemoryFactory) lts);
SegmentMemory lsmem = lmem.getSegmentMemory();
if ( lsmem == null ) {
lsmem = SegmentUtilities.createSegmentMemory(lts, this);
}
LeftInputAdapterNode.doInsertObject( handle, pCtx, lian, this, lmem, false, queryObject.isOpen() );
List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories();
for ( int i = 0, length = rmems.size(); i < length; i++ ) {
PathMemory rm = rmems.get( i );
RuleNetworkEvaluatorActivation evaluator = agenda.createRuleNetworkEvaluatorActivation( Integer.MAX_VALUE, rm, rm.getRuleTerminalNode() );
evaluator.evaluateNetwork(this, 0, -1);
}
} else {
// no need to call retract, as no leftmemory used.
getEntryPointNode().assertQuery( handle,
pCtx,
this );
pCtx.evaluateActionQueue( this );
}
return tnodes;
}
public void closeLiveQuery(final InternalFactHandle factHandle) {
try {
startOperation();
this.ruleBase.readLock();
this.lock.lock();
final PropagationContext pCtx = new PropagationContextImpl( getNextPropagationIdCounter(),
PropagationContext.INSERTION,
null,
null,
factHandle,
getEntryPoint() );
if ( this.ruleBase.getConfiguration().isPhreakEnabled() ) {
LeftInputAdapterNode lian = ( LeftInputAdapterNode ) factHandle.getFirstLeftTuple().getLeftTupleSink().getLeftTupleSource();
LiaNodeMemory lmem = (LiaNodeMemory) getNodeMemory( (MemoryFactory) lian);
SegmentMemory lsmem = lmem.getSegmentMemory();
LeftTuple childLeftTuple = factHandle.getFirstLeftTuple(); // there is only one, all other LTs are peers
LeftInputAdapterNode.doDeleteObject( childLeftTuple, childLeftTuple.getPropagationContext(), lsmem, this, lian, false, lmem );
List<PathMemory> rmems = lmem.getSegmentMemory().getPathMemories();
for ( int i = 0, length = rmems.size(); i < length; i++ ) {
PathMemory rm = rmems.get( i );
RuleNetworkEvaluatorActivation evaluator = agenda.createRuleNetworkEvaluatorActivation( Integer.MAX_VALUE, rm, rm.getRuleTerminalNode() );
evaluator.evaluateNetwork(this, 0, -1);
}
} else {
getEntryPointNode().retractQuery( factHandle,
pCtx,
this );
pCtx.evaluateActionQueue( this );
}
getFactHandleFactory().destroyFactHandle( factHandle );
} finally {
this.lock.unlock();
this.ruleBase.readUnlock();
endOperation();
}
}
public static class WorkingMemoryReteAssertAction
implements
WorkingMemoryAction {
private InternalFactHandle factHandle;
private boolean removeLogical;
private boolean updateEqualsMap;
private Rule ruleOrigin;
private LeftTuple leftTuple;
public WorkingMemoryReteAssertAction(final InternalFactHandle factHandle,
final boolean removeLogical,
final boolean updateEqualsMap,
final Rule ruleOrigin,
final LeftTuple leftTuple) {
this.factHandle = factHandle;
this.removeLogical = removeLogical;
this.updateEqualsMap = updateEqualsMap;
this.ruleOrigin = ruleOrigin;
this.leftTuple = leftTuple;
}
public WorkingMemoryReteAssertAction(MarshallerReaderContext context) throws IOException {
this.factHandle = context.handles.get( context.readInt() );
this.removeLogical = context.readBoolean();
this.updateEqualsMap = context.readBoolean();
if ( context.readBoolean() ) {
String pkgName = context.readUTF();
String ruleName = context.readUTF();
Package pkg = context.ruleBase.getPackage( pkgName );
this.ruleOrigin = pkg.getRule( ruleName );
}
if ( context.readBoolean() ) {
this.leftTuple = context.terminalTupleMap.get( context.readInt() );
}
}
public WorkingMemoryReteAssertAction(MarshallerReaderContext context,
Action _action) {
Assert _assert = _action.getAssert();
this.factHandle = context.handles.get( _assert.getHandleId() );
this.removeLogical = _assert.getRemoveLogical();
this.updateEqualsMap = _assert.getUpdateEqualsMap();
if ( _assert.hasTuple() ) {
String pkgName = _assert.getOriginPkgName();
String ruleName = _assert.getOriginRuleName();
Package pkg = context.ruleBase.getPackage( pkgName );
this.ruleOrigin = pkg.getRule( ruleName );
this.leftTuple = context.filter.getTuplesCache().get( PersisterHelper.createActivationKey( pkgName, ruleName, _assert.getTuple() ) );
}
}
public void write(MarshallerWriteContext context) throws IOException {
context.writeShort( WorkingMemoryAction.WorkingMemoryReteAssertAction );
context.writeInt( this.factHandle.getId() );
context.writeBoolean( this.removeLogical );
context.writeBoolean( this.updateEqualsMap );
if ( this.ruleOrigin != null ) {
context.writeBoolean( true );
context.writeUTF( ruleOrigin.getPackage() );
context.writeUTF( ruleOrigin.getName() );
} else {
context.writeBoolean( false );
}
if ( this.leftTuple != null ) {
context.writeBoolean( true );
context.writeInt( context.terminalTupleMap.get( this.leftTuple ) );
} else {
context.writeBoolean( false );
}
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
ProtobufMessages.ActionQueue.Assert.Builder _assert = ProtobufMessages.ActionQueue.Assert.newBuilder();
_assert.setHandleId( this.factHandle.getId() )
.setRemoveLogical( this.removeLogical )
.setUpdateEqualsMap( this.updateEqualsMap );
if ( this.leftTuple != null ) {
ProtobufMessages.Tuple.Builder _tuple = ProtobufMessages.Tuple.newBuilder();
for( LeftTuple entry = this.leftTuple; entry != null; entry = entry.getParent() ) {
_tuple.addHandleId( entry.getLastHandle().getId() );
}
_assert.setOriginPkgName( ruleOrigin.getPackageName() )
.setOriginRuleName( ruleOrigin.getName() )
.setTuple( _tuple.build() );
}
return ProtobufMessages.ActionQueue.Action.newBuilder()
.setType( ProtobufMessages.ActionQueue.ActionType.ASSERT )
.setAssert( _assert.build() )
.build();
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
factHandle = (InternalFactHandle) in.readObject();
removeLogical = in.readBoolean();
updateEqualsMap = in.readBoolean();
ruleOrigin = (Rule) in.readObject();
leftTuple = (LeftTuple) in.readObject();
}
public void writeExternal(ObjectOutput out) throws IOException {
out.writeObject( factHandle );
out.writeBoolean( removeLogical );
out.writeBoolean( updateEqualsMap );
out.writeObject( ruleOrigin );
out.writeObject( leftTuple );
}
public void execute(InternalWorkingMemory workingMemory) {
final PropagationContext context = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
PropagationContext.INSERTION,
this.ruleOrigin,
this.leftTuple,
this.factHandle );
ReteooRuleBase ruleBase = (ReteooRuleBase) workingMemory.getRuleBase();
ruleBase.assertObject( this.factHandle,
this.factHandle.getObject(),
context,
workingMemory );
context.evaluateActionQueue( workingMemory );
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
}
public static class WorkingMemoryReteExpireAction
implements
WorkingMemoryAction {
private InternalFactHandle factHandle;
private ObjectTypeNode node;
public WorkingMemoryReteExpireAction(final InternalFactHandle factHandle,
final ObjectTypeNode node) {
this.factHandle = factHandle;
this.node = node;
}
public InternalFactHandle getFactHandle() {
return factHandle;
}
public void setFactHandle(InternalFactHandle factHandle) {
this.factHandle = factHandle;
}
public ObjectTypeNode getNode() {
return node;
}
public void setNode(ObjectTypeNode node) {
this.node = node;
}
public WorkingMemoryReteExpireAction(MarshallerReaderContext context) throws IOException {
this.factHandle = context.handles.get( context.readInt() );
final int nodeId = context.readInt();
this.node = (ObjectTypeNode) context.sinks.get( Integer.valueOf( nodeId ) );
}
public WorkingMemoryReteExpireAction(MarshallerReaderContext context,
Action _action) {
this.factHandle = context.handles.get( _action.getExpire().getHandleId() );
this.node = (ObjectTypeNode) context.sinks.get( Integer.valueOf( _action.getExpire().getNodeId() ) );
}
public void write(MarshallerWriteContext context) throws IOException {
context.writeShort( WorkingMemoryAction.WorkingMemoryReteExpireAction );
context.writeInt( this.factHandle.getId() );
context.writeInt( this.node.getId() );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
return ProtobufMessages.ActionQueue.Action.newBuilder()
.setType( ProtobufMessages.ActionQueue.ActionType.EXPIRE )
.setExpire( ProtobufMessages.ActionQueue.Expire.newBuilder()
.setHandleId( this.factHandle.getId() )
.setNodeId( this.node.getId() )
.build() )
.build();
}
public void execute(InternalWorkingMemory workingMemory) {
if ( this.factHandle.isValid() ) {
// if the fact is still in the working memory (since it may have been previously retracted already
final PropagationContext context = new PropagationContextImpl( workingMemory.getNextPropagationIdCounter(),
PropagationContext.EXPIRATION,
null,
null,
this.factHandle );
((EventFactHandle) factHandle).setExpired( true );
this.node.retractObject( factHandle,
context,
workingMemory );
context.evaluateActionQueue( workingMemory );
// if no activations for this expired event
if ( ((EventFactHandle) factHandle).getActivationsCount() == 0 ) {
// remove it from the object store and clean up resources
((EventFactHandle) factHandle).getEntryPoint().retract( factHandle );
}
context.evaluateActionQueue( workingMemory );
}
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class EvaluateResultConstraints
implements
WorkingMemoryAction {
private ActivitySource source;
private LeftTuple leftTuple;
private PropagationContext context;
private InternalWorkingMemory workingMemory;
private AccumulateMemory memory;
private AccumulateContext accctx;
private boolean useLeftMemory;
private AccumulateNode node;
public EvaluateResultConstraints(PropagationContext context) {
this.context = context;
}
public EvaluateResultConstraints(ActivitySource source,
LeftTuple leftTuple,
PropagationContext context,
InternalWorkingMemory workingMemory,
AccumulateMemory memory,
AccumulateContext accctx,
boolean useLeftMemory,
AccumulateNode node) {
this.source = source;
this.leftTuple = leftTuple;
this.context = context;
this.workingMemory = workingMemory;
this.memory = memory;
this.accctx = accctx;
this.useLeftMemory = useLeftMemory;
this.node = node;
}
public EvaluateResultConstraints(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
final AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
accctx.setAction( null );
node.evaluateResultConstraints( source,
leftTuple,
context,
workingMemory,
memory,
accctx,
useLeftMemory );
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public ActivitySource getSource() {
return source;
}
public void setSource(ActivitySource source) {
this.source = source;
}
public String toString() {
return "[ResumeInsertAction leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryInsertAction
implements
WorkingMemoryAction {
private PropagationContext context;
private InternalFactHandle factHandle;
private LeftTuple leftTuple;
private QueryElementNode node;
public QueryInsertAction(PropagationContext context) {
this.context = context;
}
public QueryInsertAction(PropagationContext context,
InternalFactHandle factHandle,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.factHandle = factHandle;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryInsertAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
// we null this as it blocks this query being called, to avoid re-entrant issues. i.e. scheduling an insert and then an update, before the insert is executed
((DroolsQuery) this.factHandle.getObject()).setAction( null );
workingMemory.getEntryPointNode().assertQuery( factHandle,
context,
workingMemory );
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public String toString() {
return "[QueryInsertAction facthandle=" + factHandle + ",\n leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryUpdateAction
implements
WorkingMemoryAction {
private PropagationContext context;
private InternalFactHandle factHandle;
private LeftTuple leftTuple;
private QueryElementNode node;
public QueryUpdateAction(PropagationContext context) {
this.context = context;
}
public QueryUpdateAction(PropagationContext context,
InternalFactHandle factHandle,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.factHandle = factHandle;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryUpdateAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
workingMemory.getEntryPointNode().modifyQuery( factHandle,
context,
workingMemory );
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public String toString() {
return "[QueryInsertModifyAction facthandle=" + factHandle + ",\n leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryRetractAction
implements
WorkingMemoryAction {
private PropagationContext context;
private LeftTuple leftTuple;
private QueryElementNode node;
public QueryRetractAction(PropagationContext context) {
this.context = context;
}
public QueryRetractAction(PropagationContext context,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryRetractAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
InternalFactHandle factHandle = (InternalFactHandle) leftTuple.getObject();
if ( node.isOpenQuery() ) {
// iterate to the query terminal node, as the child leftTuples will get picked up there
workingMemory.getEntryPointNode().retractObject( factHandle,
context,
workingMemory.getObjectTypeConfigurationRegistry().getObjectTypeConf( workingMemory.getEntryPoint(),
factHandle.getObject() ),
workingMemory );
//workingMemory.getFactHandleFactory().destroyFactHandle( factHandle );
} else {
// get child left tuples, as there is no open query
if ( leftTuple.getFirstChild() != null ) {
node.getSinkPropagator().propagateRetractLeftTuple( leftTuple,
context,
workingMemory );
}
}
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public String toString() {
return "[QueryRetractAction leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryResultInsertAction
implements
WorkingMemoryAction {
private PropagationContext context;
private LeftTuple leftTuple;
private InternalFactHandle factHandle;
private QueryElementNode node;
public QueryResultInsertAction(PropagationContext context) {
this.context = context;
}
public QueryResultInsertAction(PropagationContext context,
InternalFactHandle factHandle,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.factHandle = factHandle;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryResultInsertAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
DroolsQuery query = (DroolsQuery) factHandle.getObject();
RightTupleList rightTuples = query.getResultInsertRightTupleList();
query.setResultInsertRightTupleList( null ); // null so further operations happen on a new stack element
for ( RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) {
RightTuple tmp = (RightTuple) rightTuple.getNext();
rightTuples.remove( rightTuple );
for ( LeftTuple childLeftTuple = rightTuple.firstChild; childLeftTuple != null; childLeftTuple = (LeftTuple) childLeftTuple.getRightParentNext() ) {
node.getSinkPropagator().doPropagateAssertLeftTuple( context,
workingMemory,
childLeftTuple,
childLeftTuple.getLeftTupleSink() );
}
rightTuple = tmp;
}
// @FIXME, this should work, but it's closing needed fact handles
// actually an evaluation 34 appears on the stack twice....
// if ( !node.isOpenQuery() ) {
// workingMemory.getFactHandleFactory().destroyFactHandle( this.factHandle );
// }
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public LeftTuple getLeftTuple() {
return this.leftTuple;
}
public String toString() {
return "[QueryEvaluationAction leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryResultRetractAction
implements
WorkingMemoryAction {
private PropagationContext context;
private LeftTuple leftTuple;
private InternalFactHandle factHandle;
private QueryElementNode node;
public QueryResultRetractAction(PropagationContext context,
InternalFactHandle factHandle,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.factHandle = factHandle;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryResultRetractAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
DroolsQuery query = (DroolsQuery) factHandle.getObject();
RightTupleList rightTuples = query.getResultRetractRightTupleList();
query.setResultRetractRightTupleList( null ); // null so further operations happen on a new stack element
for ( RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) {
RightTuple tmp = (RightTuple) rightTuple.getNext();
rightTuples.remove( rightTuple );
this.node.getSinkPropagator().propagateRetractRightTuple( rightTuple,
context,
workingMemory );
rightTuple = tmp;
}
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public LeftTuple getLeftTuple() {
return this.leftTuple;
}
public String toString() {
return "[QueryResultRetractAction leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryResultUpdateAction
implements
WorkingMemoryAction {
private PropagationContext context;
private LeftTuple leftTuple;
InternalFactHandle factHandle;
private QueryElementNode node;
public QueryResultUpdateAction(PropagationContext context,
InternalFactHandle factHandle,
LeftTuple leftTuple,
QueryElementNode node) {
this.context = context;
this.factHandle = factHandle;
this.leftTuple = leftTuple;
this.node = node;
}
public QueryResultUpdateAction(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
DroolsQuery query = (DroolsQuery) factHandle.getObject();
RightTupleList rightTuples = query.getResultUpdateRightTupleList();
query.setResultUpdateRightTupleList( null ); // null so further operations happen on a new stack element
for ( RightTuple rightTuple = rightTuples.getFirst(); rightTuple != null; ) {
RightTuple tmp = (RightTuple) rightTuple.getNext();
rightTuples.remove( rightTuple );
this.node.getSinkPropagator().propagateModifyChildLeftTuple( rightTuple.firstChild,
rightTuple.firstChild.getLeftParent(),
context,
workingMemory,
true );
rightTuple = tmp;
}
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public LeftTuple getLeftTuple() {
return leftTuple;
}
public String toString() {
return "[QueryResultUpdateAction leftTuple=" + leftTuple + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public static class QueryRiaFixerNodeFixer
implements
WorkingMemoryAction {
private PropagationContext context;
private LeftTuple leftTuple;
private BetaNode node;
private boolean retract;
public QueryRiaFixerNodeFixer(PropagationContext context) {
this.context = context;
}
public QueryRiaFixerNodeFixer(PropagationContext context,
LeftTuple leftTuple,
boolean retract,
BetaNode node) {
this.context = context;
this.leftTuple = leftTuple;
this.retract = retract;
this.node = node;
}
public QueryRiaFixerNodeFixer(MarshallerReaderContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void write(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public ProtobufMessages.ActionQueue.Action serialize(MarshallerWriteContext context) throws IOException {
throw new UnsupportedOperationException( "Should not be present in network on serialisation" );
}
public void execute(InternalWorkingMemory workingMemory) {
leftTuple.setLeftTupleSink( this.node );
if ( leftTuple.getFirstChild() == null ) {
this.node.assertLeftTuple( leftTuple,
context,
workingMemory );
} else {
if ( retract ) {
this.node.getSinkPropagator().propagateRetractLeftTuple( leftTuple,
context,
workingMemory );
} else {
this.node.getSinkPropagator().propagateModifyChildLeftTuple( leftTuple,
context,
workingMemory,
true );
}
}
if ( leftTuple.getLeftParent() == null ) {
// It's not an open query, as we aren't recording parent chains, so we need to clear out right memory
Object node = workingMemory.getNodeMemory( this.node );
RightTupleMemory rightMemory = null;
if ( node instanceof BetaMemory ) {
rightMemory = ((BetaMemory) node).getRightTupleMemory();
} else if ( node instanceof AccumulateMemory ) {
rightMemory = ((AccumulateMemory) node).betaMemory.getRightTupleMemory();
}
final TupleStartEqualsConstraint constraint = TupleStartEqualsConstraint.getInstance();
TupleStartEqualsConstraintContextEntry contextEntry = new TupleStartEqualsConstraintContextEntry();
contextEntry.updateFromTuple( workingMemory, leftTuple );
FastIterator rightIt = rightMemory.fastIterator();
RightTuple temp = null;
for ( RightTuple rightTuple = rightMemory.getFirst( leftTuple, (InternalFactHandle) context.getFactHandle(), rightIt ); rightTuple != null; ) {
temp = (RightTuple) rightIt.next( rightTuple );
if ( constraint.isAllowedCachedLeft( contextEntry, rightTuple.getFactHandle() ) ) {
rightMemory.remove( rightTuple );
}
rightTuple = temp;
}
}
}
public void execute(InternalKnowledgeRuntime kruntime) {
execute( ((StatefulKnowledgeSessionImpl) kruntime).getInternalWorkingMemory() );
}
public String toString() {
return "[QueryRiaFixerNodeFixer leftTuple=" + leftTuple + ",\n retract=" + retract + "]\n";
}
public void writeExternal(ObjectOutput out) throws IOException {
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
}
}
public EntryPoint getEntryPoint() {
return this.defaultEntryPoint.getEntryPoint();
}
public InternalWorkingMemory getInternalWorkingMemory() {
return this;
}
public <T extends org.kie.api.runtime.rule.FactHandle> Collection<T> getFactHandles() {
List list = new ArrayList();
for ( Iterator it = iterateFactHandles(); it.hasNext(); ) {
FactHandle fh = ( FactHandle) it.next();
list.add( fh );
}
return list;
}
public <T extends org.kie.api.runtime.rule.FactHandle> Collection<T> getFactHandles(ObjectFilter filter) {
throw new UnsupportedOperationException( "this is implementedby StatefulKnowledgeImpl" );
}
public Collection<? extends Object> getObjects() {
throw new UnsupportedOperationException( "this is implementedby StatefulKnowledgeImpl" );
}
public Collection<? extends Object> getObjects(ObjectFilter filter) {
throw new UnsupportedOperationException( "this is implementedby StatefulKnowledgeImpl" );
}
}