[jboss-svn-commits] JBL Code SVN: r36014 - in labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src: main/java/org/drools/common and 9 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sun Nov 21 18:41:00 EST 2010
Author: leo_gomes
Date: 2010-11-21 18:40:59 -0500 (Sun, 21 Nov 2010)
New Revision: 36014
Added:
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/Unlinkable.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/ConfigStep.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingComplex.nodeTestCase
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingModify.nodeTestCase
Modified:
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/RuleBaseConfiguration.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/common/PropagationContextImpl.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/ConcurrentRightTupleList.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleList.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleList.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/AbstractObjectSinkAdapter.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/spi/PropagationContext.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/RuleBaseConfigurationTest.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/JUnitNodeTestRunner.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/NodeSuiteTest.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngine.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngineTest.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/SingleTestCase.java
labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/NodeTestCase.java
Log:
Initial implementation of L&R Unlinking. Only the right side is unlinked and once it's linked it's not unlinked again.
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/RuleBaseConfiguration.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/RuleBaseConfiguration.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/RuleBaseConfiguration.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -27,6 +27,7 @@
import java.util.Properties;
import org.drools.builder.conf.ClassLoaderCacheOption;
+import org.drools.builder.conf.LRUnlinkingOption;
import org.drools.common.AgendaGroupFactory;
import org.drools.common.ArrayAgendaGroupFactory;
import org.drools.common.PriorityQueueAgendaGroupFactory;
@@ -100,7 +101,8 @@
* drools.maxThreads = <-1|1..n>
* drools.multithreadEvaluation = <true|false>
* drools.mbeans = <enabled|disabled>
- * drools.classLoaderCacheEnabled = <true|false>
+ * drools.classLoaderCacheEnabled = <true|false>
+ * drools.lrUnlinkingEnabled = <true|false>
* </pre>
*/
public class RuleBaseConfiguration
@@ -132,6 +134,7 @@
private String consequenceExceptionHandler;
private String ruleBaseUpdateHandler;
private boolean classLoaderCacheEnabled;
+ private boolean lrUnlinkingEnabled;
private EventProcessingOption eventProcessingMode;
@@ -175,6 +178,7 @@
out.writeInt( maxThreads );
out.writeObject( eventProcessingMode );
out.writeBoolean( classLoaderCacheEnabled );
+ out.writeBoolean( lrUnlinkingEnabled );
}
public void readExternal(ObjectInput in) throws IOException,
@@ -202,6 +206,7 @@
maxThreads = in.readInt();
eventProcessingMode = (EventProcessingOption) in.readObject();
classLoaderCacheEnabled = in.readBoolean();
+ lrUnlinkingEnabled = in.readBoolean();
}
/**
@@ -294,6 +299,8 @@
setMBeansEnabled( MBeansOption.isEnabled( value ) );
} else if ( name.equals( ClassLoaderCacheOption.PROPERTY_NAME ) ) {
setClassLoaderCacheEnabled( StringUtils.isEmpty( value ) ? true : Boolean.valueOf( value ) );
+ } else if ( name.equals( LRUnlinkingOption.PROPERTY_NAME ) ) {
+ setLRUnlinkingEnabled( StringUtils.isEmpty( value ) ? false : Boolean.valueOf( value ) );
}
}
@@ -347,6 +354,8 @@
return isMBeansEnabled() ? "enabled" : "disabled";
} else if ( name.equals( ClassLoaderCacheOption.PROPERTY_NAME ) ) {
return Boolean.toString( isClassLoaderCacheEnabled() );
+ } else if ( name.equals( LRUnlinkingOption.PROPERTY_NAME ) ) {
+ return Boolean.toString( isLRUnlinkingEnabled() );
}
return null;
@@ -443,6 +452,10 @@
setClassLoaderCacheEnabled( Boolean.valueOf( this.chainedProperties.getProperty( ClassLoaderCacheOption.PROPERTY_NAME,
"true" ) ) );
+
+ setLRUnlinkingEnabled( Boolean.valueOf( this.chainedProperties.getProperty( LRUnlinkingOption.PROPERTY_NAME,
+ "false" ) ) );
+
}
/**
@@ -685,7 +698,23 @@
this.classLoaderCacheEnabled = classLoaderCacheEnabled;
this.classLoader.setCachingEnabled( this.classLoaderCacheEnabled );
}
+
+ /**
+ * @return whether or not Left & Right Unlinking is enabled.
+ */
+ public boolean isLRUnlinkingEnabled() {
+ return this.lrUnlinkingEnabled;
+ }
+
+ /**
+ * Enable Left & Right Unlinking.
+ * @param enabled
+ */
+ public void setLRUnlinkingEnabled(boolean enabled) {
+ this.lrUnlinkingEnabled = enabled;
+ }
+
public List<Map<String, Object>> getWorkDefinitions() {
if ( this.workDefinitions == null ) {
initWorkDefinitions();
@@ -1046,6 +1075,8 @@
return (T) (this.isMBeansEnabled() ? MBeansOption.ENABLED : MBeansOption.DISABLED);
} else if ( ClassLoaderCacheOption.class.equals( option ) ) {
return (T) (this.isClassLoaderCacheEnabled() ? ClassLoaderCacheOption.ENABLED : ClassLoaderCacheOption.DISABLED);
+ } else if ( LRUnlinkingOption.class.equals( option ) ) {
+ return (T) (this.isLRUnlinkingEnabled() ? ClassLoaderCacheOption.ENABLED : ClassLoaderCacheOption.DISABLED);
}
return null;
@@ -1088,6 +1119,8 @@
setMBeansEnabled( ((MBeansOption) option).isEnabled() );
} else if ( option instanceof ClassLoaderCacheOption ) {
setClassLoaderCacheEnabled( ((ClassLoaderCacheOption) option).isClassLoaderCacheEnabled() );
+ } else if ( option instanceof LRUnlinkingOption ) {
+ setLRUnlinkingEnabled( ((LRUnlinkingOption) option).isLRUnlinkingEnabled() );
}
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/common/PropagationContextImpl.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/common/PropagationContextImpl.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/common/PropagationContextImpl.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -49,6 +49,8 @@
private EntryPoint entryPoint;
private int originOffset;
+
+ private int latestPropagationAttempt;
public PropagationContextImpl() {
@@ -68,6 +70,7 @@
this.dormantActivations = 0;
this.entryPoint = EntryPoint.DEFAULT;
this.originOffset = -1;
+ resetLatestPropagationAttempt();
}
public PropagationContextImpl(final long number,
@@ -87,6 +90,7 @@
this.dormantActivations = dormantActivations;
this.entryPoint = entryPoint;
this.originOffset = -1;
+ resetLatestPropagationAttempt();
}
public void readExternal(ObjectInput in) throws IOException,
@@ -99,6 +103,7 @@
this.leftTuple = (LeftTuple) in.readObject();
this.entryPoint = (EntryPoint) in.readObject();
this.originOffset = in.readInt();
+ this.latestPropagationAttempt = in.readInt();
}
public void writeExternal(ObjectOutput out) throws IOException {
@@ -110,6 +115,7 @@
out.writeObject( this.leftTuple );
out.writeObject( this.entryPoint );
out.writeInt( this.originOffset );
+ out.writeInt( this.latestPropagationAttempt );
}
public long getPropagationNumber() {
@@ -189,4 +195,20 @@
this.originOffset = originOffset;
}
+ public int getLatestPropagationAttempt() {
+ return latestPropagationAttempt;
+ }
+
+ public void setLatestPropagationAttempt() {
+ this.latestPropagationAttempt = this.factHandle.getId();
+ }
+
+ public void resetLatestPropagationAttempt() {
+ this.latestPropagationAttempt = -1;
+ }
+
+
+
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/ConcurrentRightTupleList.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/ConcurrentRightTupleList.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/ConcurrentRightTupleList.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -202,4 +202,13 @@
public Entry[] toArray() {
throw new UnsupportedOperationException( "method is not implemented yet" );
}
+
+ public void clear() {
+
+ RightTuple rightTuple = null;
+
+ while((rightTuple = (RightTuple) iterator().next()) != null) {
+ remove(rightTuple);
+ }
+ }
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleIndexHashTable.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -397,4 +397,16 @@
return builder.toString();
}
+
+ public void clear() {
+
+ LeftTuple leftTuple = null;
+
+ while((leftTuple = (LeftTuple) iterator().next()) != null) {
+ remove(leftTuple);
+ }
+ }
+
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleList.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleList.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/LeftTupleList.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -217,4 +217,14 @@
return builder.toString();
}
+
+ public void clear() {
+
+ LeftTuple leftTuple = null;
+
+ while((leftTuple = (LeftTuple) iterator().next()) != null) {
+ remove(leftTuple);
+ }
+ }
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleIndexHashTable.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -259,7 +259,7 @@
this.table.length );
RightTupleList previous = null;
RightTupleList current = (RightTupleList) this.table[index];
- while ( current != memory ) {
+ while (current != memory ) {
previous = current;
current = (RightTupleList) current.getNext();
}
@@ -417,4 +417,15 @@
return builder.toString();
}
+
+ public void clear() {
+
+ Iterator it = iterator();
+
+ for ( RightTuple rightTuple = (RightTuple) it.next(); rightTuple != null; rightTuple = (RightTuple) it.next() ) {
+ remove(rightTuple);
+ rightTuple.setMemory(null);
+ }
+ }
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleList.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleList.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/core/util/RightTupleList.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -266,4 +266,14 @@
return builder.toString();
}
+
+ public void clear() {
+
+ RightTuple rightTuple = null;
+
+ while((rightTuple = (RightTuple) iterator().next()) != null) {
+ remove(rightTuple);
+ }
+ }
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/marshalling/impl/InputMarshaller.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -1,841 +1,849 @@
-/**
- * Copyright 2010 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.marshalling.impl;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.Serializable;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Queue;
-
-import org.drools.RuntimeDroolsException;
-import org.drools.SessionConfiguration;
-import org.drools.base.ClassObjectType;
-import org.drools.common.AbstractWorkingMemory;
-import org.drools.common.AgendaItem;
-import org.drools.common.BaseNode;
-import org.drools.common.BinaryHeapQueueAgendaGroup;
-import org.drools.common.DefaultAgenda;
-import org.drools.common.DefaultFactHandle;
-import org.drools.common.EqualityKey;
-import org.drools.common.InternalAgendaGroup;
-import org.drools.common.InternalFactHandle;
-import org.drools.common.InternalRuleBase;
-import org.drools.common.InternalRuleFlowGroup;
-import org.drools.common.InternalWorkingMemory;
-import org.drools.common.NodeMemory;
-import org.drools.common.PropagationContextImpl;
-import org.drools.common.RuleFlowGroupImpl;
-import org.drools.common.TruthMaintenanceSystem;
-import org.drools.common.WorkingMemoryAction;
-import org.drools.concurrent.ExecutorService;
-import org.drools.core.util.ObjectHashMap;
-import org.drools.core.util.ObjectHashSet;
-import org.drools.impl.EnvironmentFactory;
-import org.drools.impl.StatefulKnowledgeSessionImpl;
-import org.drools.marshalling.ObjectMarshallingStrategy;
-import org.drools.process.instance.WorkItem;
-import org.drools.process.instance.impl.WorkItemImpl;
-import org.drools.reteoo.BetaMemory;
-import org.drools.reteoo.BetaNode;
-import org.drools.reteoo.EntryPointNode;
-import org.drools.reteoo.InitialFactImpl;
-import org.drools.reteoo.LeftTuple;
-import org.drools.reteoo.LeftTupleSink;
-import org.drools.reteoo.NodeTypeEnums;
-import org.drools.reteoo.ObjectTypeConf;
-import org.drools.reteoo.ObjectTypeNode;
-import org.drools.reteoo.ReteooStatefulSession;
-import org.drools.reteoo.ReteooWorkingMemory;
-import org.drools.reteoo.RightTuple;
-import org.drools.reteoo.RightTupleSink;
-import org.drools.reteoo.RuleTerminalNode;
-import org.drools.reteoo.AccumulateNode.AccumulateContext;
-import org.drools.reteoo.AccumulateNode.AccumulateMemory;
-import org.drools.reteoo.FromNode.FromMemory;
-import org.drools.rule.EntryPoint;
-import org.drools.rule.GroupElement;
-import org.drools.rule.Package;
-import org.drools.rule.Rule;
-import org.drools.runtime.Environment;
-import org.drools.runtime.rule.WorkingMemoryEntryPoint;
-import org.drools.spi.Activation;
-import org.drools.spi.AgendaGroup;
-import org.drools.spi.FactHandleFactory;
-import org.drools.spi.ObjectType;
-import org.drools.spi.PropagationContext;
-import org.drools.spi.RuleFlowGroup;
-
-public class InputMarshaller {
-
- private static ProcessMarshaller processMarshaller = createProcessMarshaller();
-
- private static ProcessMarshaller createProcessMarshaller() {
- try {
- return ProcessMarshallerFactory.newProcessMarshaller();
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
-
- /**
- * Stream the data into an existing session
- *
- * @param session
- * @param context
- * @param id
- * @param executor
- * @return
- * @throws IOException
- * @throws ClassNotFoundException
- */
- public static ReteooStatefulSession readSession(ReteooStatefulSession session,
- MarshallerReaderContext context) throws IOException,
- ClassNotFoundException {
- boolean multithread = context.readBoolean();
- int handleId = context.readInt();
- long handleCounter = context.readLong();
- long propagationCounter = context.readLong();
-
- // these are for the InitialFactHandle, on a reset we just ignore
- context.readInt();
- context.readLong();
-
- session.reset( handleId,
- handleCounter,
- propagationCounter );
- DefaultAgenda agenda = (DefaultAgenda) session.getAgenda();
-
- readAgenda( context,
- agenda );
-
- context.wm = session;
-
- context.handles.put( context.wm.getInitialFactHandle().getId(), context.wm.getInitialFactHandle() );
-
- readFactHandles( context );
-
- readActionQueue( context );
-
- if ( context.readBoolean() ) {
- readTruthMaintenanceSystem( context );
- }
-
- if ( context.marshalProcessInstances && processMarshaller != null) {
- processMarshaller.readProcessInstances( context );
- }
-
- if ( context.marshalWorkItems ) {
- processMarshaller.readWorkItems( context );
- }
-
- if (processMarshaller != null) {
- processMarshaller.readProcessTimers( context );
- }
-
- if( multithread ) {
- session.startPartitionManagers();
- }
-
- return session;
- }
-
- /**
- * Create a new session into which to read the stream data
- * @param context
- * @param id
- * @param executor
- * @return
- * @throws IOException
- * @throws ClassNotFoundException
- */
- public static ReteooStatefulSession readSession(MarshallerReaderContext context,
- int id,
- ExecutorService executor) throws IOException,
- ClassNotFoundException {
- return readSession( context, id, executor, EnvironmentFactory.newEnvironment(), new SessionConfiguration() );
- }
-
- public static ReteooStatefulSession readSession(MarshallerReaderContext context,
- int id,
- ExecutorService executor,
- Environment environment,
- SessionConfiguration config) throws IOException,
- ClassNotFoundException {
-
- boolean multithread = context.readBoolean();
-
- FactHandleFactory handleFactory = context.ruleBase.newFactHandleFactory( context.readInt(),
- context.readLong() );
-
- InternalFactHandle initialFactHandle = new DefaultFactHandle( context.readInt(), //id
- InitialFactImpl.getInstance(),
- context.readLong(),
- null);
-
- context.handles.put( initialFactHandle.getId(),
- initialFactHandle );
-
- long propagationCounter = context.readLong();
-
- DefaultAgenda agenda = new DefaultAgenda( context.ruleBase,
- false );
- readAgenda( context,
- agenda );
- ReteooStatefulSession session = new ReteooStatefulSession( id,
- context.ruleBase,
- executor,
- handleFactory,
- initialFactHandle,
- propagationCounter,
- config,
- agenda,
- environment );
- session.setKnowledgeRuntime(new StatefulKnowledgeSessionImpl(session));
-
- initialFactHandle.setEntryPoint( session.getEntryPoints().get( EntryPoint.DEFAULT.getEntryPointId() ) );
-
- // RuleFlowGroups need to reference the session
- for ( RuleFlowGroup group : agenda.getRuleFlowGroupsMap().values() ) {
- ((RuleFlowGroupImpl) group).setWorkingMemory( session );
- }
- context.wm = session;
-
- readFactHandles( context );
-
- readActionQueue( context );
-
- readTruthMaintenanceSystem( context );
-
- if ( context.marshalProcessInstances && processMarshaller != null ) {
- processMarshaller.readProcessInstances( context );
- }
-
- if ( context.marshalWorkItems && processMarshaller != null ) {
- processMarshaller.readWorkItems( context );
- }
-
- if ( processMarshaller != null ) {
- processMarshaller.readProcessTimers( context );
- }
-
- if( multithread ) {
- session.startPartitionManagers();
- }
-
- return session;
- }
-
- public static void readAgenda(MarshallerReaderContext context,
- DefaultAgenda agenda) throws IOException {
- ObjectInputStream stream = context.stream;
- while ( stream.readShort() == PersisterEnums.AGENDA_GROUP ) {
- BinaryHeapQueueAgendaGroup group = new BinaryHeapQueueAgendaGroup( stream.readUTF(),
- context.ruleBase );
- group.setActive( stream.readBoolean() );
- agenda.getAgendaGroupsMap().put( group.getName(),
- group );
- }
-
- while ( stream.readShort() == PersisterEnums.AGENDA_GROUP ) {
- String agendaGroupName = stream.readUTF();
- agenda.getStackList().add( agenda.getAgendaGroup( agendaGroupName ) );
- }
-
- while ( stream.readShort() == PersisterEnums.RULE_FLOW_GROUP ) {
- String rfgName = stream.readUTF();
- boolean active = stream.readBoolean();
- boolean autoDeactivate = stream.readBoolean();
- RuleFlowGroupImpl rfg = new RuleFlowGroupImpl( rfgName,
- active,
- autoDeactivate );
- agenda.getRuleFlowGroupsMap().put( rfgName,
- rfg );
- int nbNodeInstances = stream.readInt();
- for (int i = 0; i < nbNodeInstances; i++) {
- Long processInstanceId = stream.readLong();
- String nodeInstanceId = stream.readUTF();
- rfg.addNodeInstance(processInstanceId, nodeInstanceId);
- }
- }
-
- }
-
- public static void readActionQueue(MarshallerReaderContext context) throws IOException, ClassNotFoundException {
- ReteooWorkingMemory wm = (ReteooWorkingMemory) context.wm;
- Queue<WorkingMemoryAction> actionQueue = wm.getActionQueue();
- while ( context.readShort() == PersisterEnums.WORKING_MEMORY_ACTION ) {
- actionQueue.offer( PersisterHelper.readWorkingMemoryAction( context ) );
- }
- }
-
- public static void readTruthMaintenanceSystem(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
-
- TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
- while ( stream.readShort() == PersisterEnums.EQUALITY_KEY ) {
- int status = stream.readInt();
- int factHandleId = stream.readInt();
- InternalFactHandle handle = (InternalFactHandle) context.handles.get( factHandleId );
-
- // ObjectTypeConf state is not marshalled, so it needs to be re-determined
- ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( context.wm.getEntryPoint(), handle.getObject() );
- if ( !typeConf.isTMSEnabled() ) {
- typeConf.enableTMS();
- }
-
- EqualityKey key = new EqualityKey( handle,
- status );
- handle.setEqualityKey( key );
- while ( stream.readShort() == PersisterEnums.FACT_HANDLE ) {
- factHandleId = stream.readInt();
- handle = (InternalFactHandle) context.handles.get( factHandleId );
- key.addFactHandle( handle );
- handle.setEqualityKey( key );
- }
- tms.put( key );
- }
- }
-
- public static void readFactHandles(MarshallerReaderContext context) throws IOException,
- ClassNotFoundException {
- ObjectInputStream stream = context.stream;
- InternalRuleBase ruleBase = context.ruleBase;
- InternalWorkingMemory wm = context.wm;
-
- if ( stream.readBoolean() ) {
- InternalFactHandle initialFactHandle = wm.getInitialFactHandle();
- int sinkId = stream.readInt();
- ObjectTypeNode initialFactNode = (ObjectTypeNode) context.sinks.get( sinkId );
- ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory( initialFactNode );
-
- initialFactMemory.add( initialFactHandle );
- readRightTuples( initialFactHandle,
- context );
- }
-
- int size = stream.readInt();
-
- // load the handles
- InternalFactHandle[] handles = new InternalFactHandle[size];
- for ( int i = 0; i < size; i++ ) {
- InternalFactHandle handle = readFactHandle( context );
-
- context.handles.put( handle.getId(),
- handle );
- handles[i] = handle;
-
- context.wm.getObjectStore().addHandle( handle,
- handle.getObject() );
-
- readRightTuples( handle,
- context );
- }
-
- EntryPointNode node = ruleBase.getRete().getEntryPointNode( EntryPoint.DEFAULT );
- Map<ObjectType, ObjectTypeNode> objectTypeNodes = node.getObjectTypeNodes();
-
- // add handles to object type nodes
- for ( InternalFactHandle handle : handles ) {
- Object object = handle.getObject();
- ClassObjectType objectType = new ClassObjectType( object.getClass() );
- ObjectTypeNode objectTypeNode = objectTypeNodes.get( objectType );
- if (objectTypeNode != null) {
- ObjectHashSet set = (ObjectHashSet) context.wm.getNodeMemory( objectTypeNode );
- set.add( handle,
- false );
- }
- }
-
- InternalFactHandle handle = wm.getInitialFactHandle();
- while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
- LeftTupleSink sink = (LeftTupleSink) context.sinks.get( stream.readInt() );
- LeftTuple leftTuple = new LeftTuple( handle,
- sink,
- true );
- readLeftTuple( leftTuple,
- context );
- }
-
- readLeftTuples( context );
-
- readPropagationContexts( context );
-
- readActivations( context );
- }
-
- public static InternalFactHandle readFactHandle(MarshallerReaderContext context) throws IOException,
- ClassNotFoundException {
- int id = context.stream.readInt();
- long recency = context.stream.readLong();
-
- int strategyIndex = context.stream.readInt();
- ObjectMarshallingStrategy strategy = context.resolverStrategyFactory.getStrategy( strategyIndex );
- Object object = strategy.read( context.stream );
-
- WorkingMemoryEntryPoint entryPoint = null;
- if(context.readBoolean()){
- String entryPointId = context.readUTF();
- if(entryPointId != null && !entryPointId.equals("")){
- entryPoint = context.wm.getEntryPoints().get(entryPointId);
- }
- }
-
- InternalFactHandle handle = new DefaultFactHandle( id,
- object,
- recency,
- entryPoint );
-
- return handle;
- }
-
- public static void readRightTuples(InternalFactHandle factHandle,
- MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
- while ( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
- readRightTuple( context,
- factHandle );
- }
- }
-
- public static void readRightTuple(MarshallerReaderContext context,
- InternalFactHandle factHandle) throws IOException {
- ObjectInputStream stream = context.stream;
-
- int sinkId = stream.readInt();
- RightTupleSink sink = (sinkId >= 0) ? (RightTupleSink) context.sinks.get( sinkId ) : null;
-
- RightTuple rightTuple = new RightTuple( factHandle,
- sink );
- context.rightTuples.put( new RightTupleKey( factHandle.getId(),
- sink ),
- rightTuple );
-
- if( sink != null ) {
- BetaMemory memory = null;
- switch ( sink.getType() ) {
- case NodeTypeEnums.AccumulateNode : {
- memory = ((AccumulateMemory) context.wm.getNodeMemory( (BetaNode) sink )).betaMemory;
- break;
- }
- default : {
- memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
- break;
- }
- }
- memory.getRightTupleMemory().add( rightTuple );
- }
- }
-
- public static void readLeftTuples(MarshallerReaderContext context) throws IOException,
- ClassNotFoundException {
- ObjectInputStream stream = context.stream;
-
- while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
- int nodeId = stream.readInt();
- LeftTupleSink sink = (LeftTupleSink) context.sinks.get( nodeId );
- int factHandleId = stream.readInt();
- LeftTuple leftTuple = new LeftTuple( context.handles.get( factHandleId ),
- sink,
- true );
- readLeftTuple( leftTuple,
- context );
- }
- }
-
- public static void readLeftTuple(LeftTuple parentLeftTuple,
- MarshallerReaderContext context) throws IOException,
- ClassNotFoundException {
- ObjectInputStream stream = context.stream;
- Map<Integer, BaseNode> sinks = context.sinks;
-
- LeftTupleSink sink = parentLeftTuple.getLeftTupleSink();
-
- switch ( sink.getType() ) {
- case NodeTypeEnums.JoinNode : {
- BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
- memory.getLeftTupleMemory().add( parentLeftTuple );
-
- while ( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- int factHandleId = stream.readInt();
- RightTupleKey key = new RightTupleKey( factHandleId,
- sink );
- RightTuple rightTuple = context.rightTuples.get( key );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- rightTuple,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- }
- break;
-
- }
- case NodeTypeEnums.EvalConditionNode : {
- while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- }
- break;
- }
- case NodeTypeEnums.NotNode :
- case NodeTypeEnums.ForallNotNode : {
- BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
- int type = stream.readShort();
- if ( type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED ) {
- memory.getLeftTupleMemory().add( parentLeftTuple );
-
- while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- }
-
- } else {
- int factHandleId = stream.readInt();
- RightTupleKey key = new RightTupleKey( factHandleId,
- sink );
- RightTuple rightTuple = context.rightTuples.get( key );
-
- parentLeftTuple.setBlocker( rightTuple );
- rightTuple.addBlocked( parentLeftTuple );
- }
- break;
- }
- case NodeTypeEnums.ExistsNode : {
- BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
- int type = stream.readShort();
- if ( type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED ) {
- memory.getLeftTupleMemory().add( parentLeftTuple );
- } else {
- int factHandleId = stream.readInt();
- RightTupleKey key = new RightTupleKey( factHandleId,
- sink );
- RightTuple rightTuple = context.rightTuples.get( key );
-
- parentLeftTuple.setBlocker( rightTuple );
- rightTuple.addBlocked( parentLeftTuple );
-
- while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- }
- }
- break;
- }
- case NodeTypeEnums.AccumulateNode : {
- // accumulate nodes generate new facts on-demand and need special procedures when de-serializing from persistent storage
- AccumulateMemory memory = (AccumulateMemory) context.wm.getNodeMemory( (BetaNode) sink );
- memory.betaMemory.getLeftTupleMemory().add( parentLeftTuple );
-
- AccumulateContext accctx = new AccumulateContext();
- memory.betaMemory.getCreatedHandles().put( parentLeftTuple,
- accctx,
- false );
- // first we de-serialize the generated fact handle
- InternalFactHandle handle = readFactHandle( context );
- accctx.result = new RightTuple( handle,
- (RightTupleSink) sink );
-
- // then we de-serialize the associated accumulation context
- accctx.context = (Serializable) stream.readObject();
- // then we de-serialize the boolean propagated flag
- accctx.propagated = stream.readBoolean();
-
- // then we de-serialize all the propagated tuples
- short head = -1;
- while ( (head = stream.readShort()) != PersisterEnums.END ) {
- switch ( head ) {
- case PersisterEnums.RIGHT_TUPLE : {
- int factHandleId = stream.readInt();
- RightTupleKey key = new RightTupleKey( factHandleId,
- sink );
- RightTuple rightTuple = context.rightTuples.get( key );
- // just wiring up the match record
- new LeftTuple( parentLeftTuple,
- rightTuple,
- sink,
- true );
- break;
- }
- case PersisterEnums.LEFT_TUPLE : {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- accctx.result,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- break;
- }
- default : {
- throw new RuntimeDroolsException( "Marshalling error. This is a bug. Please contact the development team." );
- }
- }
- }
- break;
- }
- case NodeTypeEnums.RightInputAdaterNode : {
- // RIANs generate new fact handles on-demand to wrap tuples and need special procedures when de-serializing from persistent storage
- ObjectHashMap memory = (ObjectHashMap) context.wm.getNodeMemory( (NodeMemory) sink );
- // create fact handle
- int id = stream.readInt();
- long recency = stream.readLong();
- InternalFactHandle handle = new DefaultFactHandle( id,
- parentLeftTuple,
- recency,
- context.wm.getEntryPoints().get( EntryPoint.DEFAULT.getEntryPointId() ) );
- memory.put( parentLeftTuple, handle );
-
- readRightTuples( handle, context );
-
- stream.readShort(); // Persistence.END
- break;
- }
- case NodeTypeEnums.FromNode: {
-// context.out.println( "FromNode" );
- // FNs generate new fact handles on-demand to wrap objects and need special procedures when serializing to persistent storage
- FromMemory memory = (FromMemory) context.wm.getNodeMemory( (NodeMemory) sink );
-
- memory.betaMemory.getLeftTupleMemory().add( parentLeftTuple );
- Map<Object, RightTuple> matches = new LinkedHashMap<Object, RightTuple>();
- memory.betaMemory.getCreatedHandles().put( parentLeftTuple, matches );
-
- while( stream.readShort() == PersisterEnums.FACT_HANDLE ) {
- // we de-serialize the generated fact handle ID
- InternalFactHandle handle = readFactHandle( context );
- context.handles.put( handle.getId(),
- handle );
- readRightTuples( handle,
- context );
- matches.put( handle.getObject(), handle.getFirstRightTuple() );
- }
- while( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
- LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
- int factHandleId = stream.readInt();
- RightTupleKey key = new RightTupleKey( factHandleId,
- null ); // created tuples in from node always use null sink
- RightTuple rightTuple = context.rightTuples.get( key );
- LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
- rightTuple,
- childSink,
- true );
- readLeftTuple( childLeftTuple,
- context );
- }
-// context.out.println( "FromNode --- END" );
- break;
- }
- case NodeTypeEnums.RuleTerminalNode : {
- int pos = context.terminalTupleMap.size();
- context.terminalTupleMap.put( pos,
- parentLeftTuple );
- break;
- }
- }
- }
-
- public static void readActivations(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
-
- while ( stream.readShort() == PersisterEnums.ACTIVATION ) {
- readActivation( context );
- }
- }
-
- public static Activation readActivation(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
- InternalRuleBase ruleBase = context.ruleBase;
- InternalWorkingMemory wm = context.wm;
-
- long activationNumber = stream.readLong();
-
- int pos = stream.readInt();
- LeftTuple leftTuple = context.terminalTupleMap.get( pos );
-
- int salience = stream.readInt();
-
- //PropagationContext context,
- String pkgName = stream.readUTF();
- String ruleName = stream.readUTF();
- Package pkg = ruleBase.getPackage( pkgName );
- Rule rule = pkg.getRule( ruleName );
-
- RuleTerminalNode ruleTerminalNode = (RuleTerminalNode) leftTuple.getLeftTupleSink();
- GroupElement subRule = ruleTerminalNode.getSubRule();
-
- PropagationContext pc = context.propagationContexts.get( stream.readLong() );
-
- AgendaItem activation = new AgendaItem( activationNumber,
- leftTuple,
- salience,
- pc,
- rule,
- subRule );
-
- leftTuple.setObject( activation );
-
- if ( stream.readBoolean() ) {
- String activationGroupName = stream.readUTF();
- ((DefaultAgenda) wm.getAgenda()).getActivationGroup( activationGroupName ).addActivation( activation );
- }
-
- boolean activated = stream.readBoolean();
- activation.setActivated( activated );
-
- InternalAgendaGroup agendaGroup;
- if ( rule.getAgendaGroup() == null || rule.getAgendaGroup().equals( "" ) || rule.getAgendaGroup().equals( AgendaGroup.MAIN ) ) {
- // Is the Rule AgendaGroup undefined? If it is use MAIN,
- // which is added to the Agenda by default
- agendaGroup = (InternalAgendaGroup) ((DefaultAgenda) wm.getAgenda()).getAgendaGroup( AgendaGroup.MAIN );
- } else {
- // AgendaGroup is defined, so try and get the AgendaGroup
- // from the Agenda
- agendaGroup = (InternalAgendaGroup) ((DefaultAgenda) wm.getAgenda()).getAgendaGroup( rule.getAgendaGroup() );
- }
-
- activation.setAgendaGroup( agendaGroup );
-
- if ( activated ) {
- if ( rule.getRuleFlowGroup() == null ) {
- agendaGroup.add( activation );
- } else {
- InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) ((DefaultAgenda) wm.getAgenda()).getRuleFlowGroup( rule.getRuleFlowGroup() );
- rfg.addActivation( activation );
- }
- }
-
- TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
- while ( stream.readShort() == PersisterEnums.LOGICAL_DEPENDENCY ) {
- int factHandleId = stream.readInt();
- InternalFactHandle handle = (InternalFactHandle) context.handles.get( factHandleId );
- tms.addLogicalDependency( handle,
- activation,
- pc,
- rule );
- }
-
- return activation;
- }
-
- public static void readPropagationContexts(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
-
- while ( stream.readShort() == PersisterEnums.PROPAGATION_CONTEXT ) {
- readPropagationContext( context );
- }
-
- }
-
- public static void readPropagationContext(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
- InternalRuleBase ruleBase = context.ruleBase;
-
- int type = stream.readInt();
-
- Rule rule = null;
- if ( stream.readBoolean() ) {
- String pkgName = stream.readUTF();
- String ruleName = stream.readUTF();
- Package pkg = ruleBase.getPackage( pkgName );
- rule = pkg.getRule( ruleName );
- }
-
- LeftTuple leftTuple = null;
- if ( stream.readBoolean() ) {
- int tuplePos = stream.readInt();
- leftTuple = (LeftTuple) context.terminalTupleMap.get( tuplePos );
- }
-
- long propagationNumber = stream.readLong();
-
- int factHandleId = stream.readInt();
- InternalFactHandle factHandle = context.handles.get( factHandleId );
-
- int activeActivations = stream.readInt();
- int dormantActivations = stream.readInt();
- String entryPointId = stream.readUTF();
-
- EntryPoint entryPoint = context.entryPoints.get( entryPointId );
- if ( entryPoint == null ) {
- entryPoint = new EntryPoint( entryPointId );
- context.entryPoints.put( entryPointId,
- entryPoint );
- }
-
- PropagationContext pc = new PropagationContextImpl( propagationNumber,
- type,
- rule,
- leftTuple,
- factHandle,
- activeActivations,
- dormantActivations,
- entryPoint );
- context.propagationContexts.put( propagationNumber,
- pc );
- }
-
- public static WorkItem readWorkItem(MarshallerReaderContext context) throws IOException {
- ObjectInputStream stream = context.stream;
-
- WorkItemImpl workItem = new WorkItemImpl();
- workItem.setId( stream.readLong() );
- workItem.setProcessInstanceId( stream.readLong() );
- workItem.setName( stream.readUTF() );
- workItem.setState( stream.readInt() );
-
- //WorkItem Paramaters
- int nbVariables = stream.readInt();
- if (nbVariables > 0) {
-
- for (int i = 0; i < nbVariables; i++) {
- String name = stream.readUTF();
- try {
- int index = stream.readInt();
- ObjectMarshallingStrategy strategy = context.resolverStrategyFactory.getStrategy(index);
-
- Object value = strategy.read(stream);
- workItem.setParameter(name, value);
- } catch (ClassNotFoundException e) {
- throw new IllegalArgumentException(
- "Could not reload variable " + name);
- }
- }
- }
-
-
-
-
- return workItem;
- }
-
-
-
-}
+/**
+ * Copyright 2010 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.marshalling.impl;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Queue;
+
+import org.drools.RuntimeDroolsException;
+import org.drools.SessionConfiguration;
+import org.drools.base.ClassObjectType;
+import org.drools.common.AbstractWorkingMemory;
+import org.drools.common.AgendaItem;
+import org.drools.common.BaseNode;
+import org.drools.common.BinaryHeapQueueAgendaGroup;
+import org.drools.common.DefaultAgenda;
+import org.drools.common.DefaultFactHandle;
+import org.drools.common.EqualityKey;
+import org.drools.common.InternalAgendaGroup;
+import org.drools.common.InternalFactHandle;
+import org.drools.common.InternalRuleBase;
+import org.drools.common.InternalRuleFlowGroup;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
+import org.drools.common.PropagationContextImpl;
+import org.drools.common.RuleFlowGroupImpl;
+import org.drools.common.TruthMaintenanceSystem;
+import org.drools.common.WorkingMemoryAction;
+import org.drools.concurrent.ExecutorService;
+import org.drools.core.util.ObjectHashMap;
+import org.drools.core.util.ObjectHashSet;
+import org.drools.impl.EnvironmentFactory;
+import org.drools.impl.StatefulKnowledgeSessionImpl;
+import org.drools.marshalling.ObjectMarshallingStrategy;
+import org.drools.process.instance.WorkItem;
+import org.drools.process.instance.impl.WorkItemImpl;
+import org.drools.reteoo.BetaMemory;
+import org.drools.reteoo.BetaNode;
+import org.drools.reteoo.EntryPointNode;
+import org.drools.reteoo.InitialFactImpl;
+import org.drools.reteoo.LeftTuple;
+import org.drools.reteoo.LeftTupleSink;
+import org.drools.reteoo.NodeTypeEnums;
+import org.drools.reteoo.ObjectTypeConf;
+import org.drools.reteoo.ObjectTypeNode;
+import org.drools.reteoo.ReteooStatefulSession;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.reteoo.RightTuple;
+import org.drools.reteoo.RightTupleSink;
+import org.drools.reteoo.RuleTerminalNode;
+import org.drools.reteoo.AccumulateNode.AccumulateContext;
+import org.drools.reteoo.AccumulateNode.AccumulateMemory;
+import org.drools.reteoo.FromNode.FromMemory;
+import org.drools.rule.EntryPoint;
+import org.drools.rule.GroupElement;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.runtime.Environment;
+import org.drools.runtime.rule.WorkingMemoryEntryPoint;
+import org.drools.spi.Activation;
+import org.drools.spi.AgendaGroup;
+import org.drools.spi.FactHandleFactory;
+import org.drools.spi.ObjectType;
+import org.drools.spi.PropagationContext;
+import org.drools.spi.RuleFlowGroup;
+
+public class InputMarshaller {
+
+ private static ProcessMarshaller processMarshaller = createProcessMarshaller();
+
+ private static ProcessMarshaller createProcessMarshaller() {
+ try {
+ return ProcessMarshallerFactory.newProcessMarshaller();
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Stream the data into an existing session
+ *
+ * @param session
+ * @param context
+ * @param id
+ * @param executor
+ * @return
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ public static ReteooStatefulSession readSession(ReteooStatefulSession session,
+ MarshallerReaderContext context) throws IOException,
+ ClassNotFoundException {
+ boolean multithread = context.readBoolean();
+ int handleId = context.readInt();
+ long handleCounter = context.readLong();
+ long propagationCounter = context.readLong();
+
+ // these are for the InitialFactHandle, on a reset we just ignore
+ context.readInt();
+ context.readLong();
+
+ session.reset( handleId,
+ handleCounter,
+ propagationCounter );
+ DefaultAgenda agenda = (DefaultAgenda) session.getAgenda();
+
+ readAgenda( context,
+ agenda );
+
+ context.wm = session;
+
+ context.handles.put( context.wm.getInitialFactHandle().getId(), context.wm.getInitialFactHandle() );
+
+ readFactHandles( context );
+
+ readActionQueue( context );
+
+ if ( context.readBoolean() ) {
+ readTruthMaintenanceSystem( context );
+ }
+
+ if ( context.marshalProcessInstances && processMarshaller != null) {
+ processMarshaller.readProcessInstances( context );
+ }
+
+ if ( context.marshalWorkItems ) {
+ processMarshaller.readWorkItems( context );
+ }
+
+ if (processMarshaller != null) {
+ processMarshaller.readProcessTimers( context );
+ }
+
+ if( multithread ) {
+ session.startPartitionManagers();
+ }
+
+ return session;
+ }
+
+ /**
+ * Create a new session into which to read the stream data
+ * @param context
+ * @param id
+ * @param executor
+ * @return
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ public static ReteooStatefulSession readSession(MarshallerReaderContext context,
+ int id,
+ ExecutorService executor) throws IOException,
+ ClassNotFoundException {
+ return readSession( context, id, executor, EnvironmentFactory.newEnvironment(), new SessionConfiguration() );
+ }
+
+ public static ReteooStatefulSession readSession(MarshallerReaderContext context,
+ int id,
+ ExecutorService executor,
+ Environment environment,
+ SessionConfiguration config) throws IOException,
+ ClassNotFoundException {
+
+ boolean multithread = context.readBoolean();
+
+ FactHandleFactory handleFactory = context.ruleBase.newFactHandleFactory( context.readInt(),
+ context.readLong() );
+
+ InternalFactHandle initialFactHandle = new DefaultFactHandle( context.readInt(), //id
+ InitialFactImpl.getInstance(),
+ context.readLong(),
+ null);
+
+ context.handles.put( initialFactHandle.getId(),
+ initialFactHandle );
+
+ long propagationCounter = context.readLong();
+
+ DefaultAgenda agenda = new DefaultAgenda( context.ruleBase,
+ false );
+ readAgenda( context,
+ agenda );
+ ReteooStatefulSession session = new ReteooStatefulSession( id,
+ context.ruleBase,
+ executor,
+ handleFactory,
+ initialFactHandle,
+ propagationCounter,
+ config,
+ agenda,
+ environment );
+ session.setKnowledgeRuntime(new StatefulKnowledgeSessionImpl(session));
+
+ initialFactHandle.setEntryPoint( session.getEntryPoints().get( EntryPoint.DEFAULT.getEntryPointId() ) );
+
+ // RuleFlowGroups need to reference the session
+ for ( RuleFlowGroup group : agenda.getRuleFlowGroupsMap().values() ) {
+ ((RuleFlowGroupImpl) group).setWorkingMemory( session );
+ }
+ context.wm = session;
+
+ readFactHandles( context );
+
+ readActionQueue( context );
+
+ readTruthMaintenanceSystem( context );
+
+ if ( context.marshalProcessInstances && processMarshaller != null ) {
+ processMarshaller.readProcessInstances( context );
+ }
+
+ if ( context.marshalWorkItems && processMarshaller != null ) {
+ processMarshaller.readWorkItems( context );
+ }
+
+ if ( processMarshaller != null ) {
+ processMarshaller.readProcessTimers( context );
+ }
+
+ if( multithread ) {
+ session.startPartitionManagers();
+ }
+
+ return session;
+ }
+
+ public static void readAgenda(MarshallerReaderContext context,
+ DefaultAgenda agenda) throws IOException {
+ ObjectInputStream stream = context.stream;
+ while ( stream.readShort() == PersisterEnums.AGENDA_GROUP ) {
+ BinaryHeapQueueAgendaGroup group = new BinaryHeapQueueAgendaGroup( stream.readUTF(),
+ context.ruleBase );
+ group.setActive( stream.readBoolean() );
+ agenda.getAgendaGroupsMap().put( group.getName(),
+ group );
+ }
+
+ while ( stream.readShort() == PersisterEnums.AGENDA_GROUP ) {
+ String agendaGroupName = stream.readUTF();
+ agenda.getStackList().add( agenda.getAgendaGroup( agendaGroupName ) );
+ }
+
+ while ( stream.readShort() == PersisterEnums.RULE_FLOW_GROUP ) {
+ String rfgName = stream.readUTF();
+ boolean active = stream.readBoolean();
+ boolean autoDeactivate = stream.readBoolean();
+ RuleFlowGroupImpl rfg = new RuleFlowGroupImpl( rfgName,
+ active,
+ autoDeactivate );
+ agenda.getRuleFlowGroupsMap().put( rfgName,
+ rfg );
+ int nbNodeInstances = stream.readInt();
+ for (int i = 0; i < nbNodeInstances; i++) {
+ Long processInstanceId = stream.readLong();
+ String nodeInstanceId = stream.readUTF();
+ rfg.addNodeInstance(processInstanceId, nodeInstanceId);
+ }
+ }
+
+ }
+
+ public static void readActionQueue(MarshallerReaderContext context) throws IOException, ClassNotFoundException {
+ ReteooWorkingMemory wm = (ReteooWorkingMemory) context.wm;
+ Queue<WorkingMemoryAction> actionQueue = wm.getActionQueue();
+ while ( context.readShort() == PersisterEnums.WORKING_MEMORY_ACTION ) {
+ actionQueue.offer( PersisterHelper.readWorkingMemoryAction( context ) );
+ }
+ }
+
+ public static void readTruthMaintenanceSystem(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+
+ TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
+ while ( stream.readShort() == PersisterEnums.EQUALITY_KEY ) {
+ int status = stream.readInt();
+ int factHandleId = stream.readInt();
+ InternalFactHandle handle = (InternalFactHandle) context.handles.get( factHandleId );
+
+ // ObjectTypeConf state is not marshalled, so it needs to be re-determined
+ ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( context.wm.getEntryPoint(), handle.getObject() );
+ if ( !typeConf.isTMSEnabled() ) {
+ typeConf.enableTMS();
+ }
+
+ EqualityKey key = new EqualityKey( handle,
+ status );
+ handle.setEqualityKey( key );
+ while ( stream.readShort() == PersisterEnums.FACT_HANDLE ) {
+ factHandleId = stream.readInt();
+ handle = (InternalFactHandle) context.handles.get( factHandleId );
+ key.addFactHandle( handle );
+ handle.setEqualityKey( key );
+ }
+ tms.put( key );
+ }
+ }
+
+ public static void readFactHandles(MarshallerReaderContext context) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream stream = context.stream;
+ InternalRuleBase ruleBase = context.ruleBase;
+ InternalWorkingMemory wm = context.wm;
+
+ if ( stream.readBoolean() ) {
+ InternalFactHandle initialFactHandle = wm.getInitialFactHandle();
+ int sinkId = stream.readInt();
+ ObjectTypeNode initialFactNode = (ObjectTypeNode) context.sinks.get( sinkId );
+ ObjectHashSet initialFactMemory = (ObjectHashSet) context.wm.getNodeMemory( initialFactNode );
+
+ initialFactMemory.add( initialFactHandle );
+ readRightTuples( initialFactHandle,
+ context );
+ }
+
+ int size = stream.readInt();
+
+ // load the handles
+ InternalFactHandle[] handles = new InternalFactHandle[size];
+ for ( int i = 0; i < size; i++ ) {
+ InternalFactHandle handle = readFactHandle( context );
+
+ context.handles.put( handle.getId(),
+ handle );
+ handles[i] = handle;
+
+ context.wm.getObjectStore().addHandle( handle,
+ handle.getObject() );
+
+ readRightTuples( handle,
+ context );
+ }
+
+ EntryPointNode node = ruleBase.getRete().getEntryPointNode( EntryPoint.DEFAULT );
+ Map<ObjectType, ObjectTypeNode> objectTypeNodes = node.getObjectTypeNodes();
+
+ // add handles to object type nodes
+ for ( InternalFactHandle handle : handles ) {
+ Object object = handle.getObject();
+ ClassObjectType objectType = new ClassObjectType( object.getClass() );
+ ObjectTypeNode objectTypeNode = objectTypeNodes.get( objectType );
+ if (objectTypeNode != null) {
+ ObjectHashSet set = (ObjectHashSet) context.wm.getNodeMemory( objectTypeNode );
+ set.add( handle,
+ false );
+ }
+ }
+
+ InternalFactHandle handle = wm.getInitialFactHandle();
+ while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
+ LeftTupleSink sink = (LeftTupleSink) context.sinks.get( stream.readInt() );
+ LeftTuple leftTuple = new LeftTuple( handle,
+ sink,
+ true );
+ readLeftTuple( leftTuple,
+ context );
+ }
+
+ readLeftTuples( context );
+
+ readPropagationContexts( context );
+
+ readActivations( context );
+ }
+
+ public static InternalFactHandle readFactHandle(MarshallerReaderContext context) throws IOException,
+ ClassNotFoundException {
+ int id = context.stream.readInt();
+ long recency = context.stream.readLong();
+
+ int strategyIndex = context.stream.readInt();
+ ObjectMarshallingStrategy strategy = context.resolverStrategyFactory.getStrategy( strategyIndex );
+ Object object = strategy.read( context.stream );
+
+ WorkingMemoryEntryPoint entryPoint = null;
+ if(context.readBoolean()){
+ String entryPointId = context.readUTF();
+ if(entryPointId != null && !entryPointId.equals("")){
+ entryPoint = context.wm.getEntryPoints().get(entryPointId);
+ }
+ }
+
+ InternalFactHandle handle = new DefaultFactHandle( id,
+ object,
+ recency,
+ entryPoint );
+
+ return handle;
+ }
+
+ public static void readRightTuples(InternalFactHandle factHandle,
+ MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+ while ( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
+ readRightTuple( context,
+ factHandle );
+ }
+ }
+
+ public static void readRightTuple(MarshallerReaderContext context,
+ InternalFactHandle factHandle) throws IOException {
+ ObjectInputStream stream = context.stream;
+
+ int sinkId = stream.readInt();
+ RightTupleSink sink = (sinkId >= 0) ? (RightTupleSink) context.sinks.get( sinkId ) : null;
+
+ RightTuple rightTuple = new RightTuple( factHandle,
+ sink );
+ context.rightTuples.put( new RightTupleKey( factHandle.getId(),
+ sink ),
+ rightTuple );
+
+ if( sink != null ) {
+ BetaMemory memory = null;
+ switch ( sink.getType() ) {
+ case NodeTypeEnums.AccumulateNode : {
+ memory = ((AccumulateMemory) context.wm.getNodeMemory( (BetaNode) sink )).betaMemory;
+ break;
+ }
+ default : {
+ memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
+ break;
+ }
+ }
+ memory.getRightTupleMemory().add( rightTuple );
+ memory.linkLeft();
+ }
+ }
+
+ public static void readLeftTuples(MarshallerReaderContext context) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream stream = context.stream;
+
+ while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
+ int nodeId = stream.readInt();
+ LeftTupleSink sink = (LeftTupleSink) context.sinks.get( nodeId );
+ int factHandleId = stream.readInt();
+ LeftTuple leftTuple = new LeftTuple( context.handles.get( factHandleId ),
+ sink,
+ true );
+ readLeftTuple( leftTuple,
+ context );
+ }
+ }
+
+ public static void readLeftTuple(LeftTuple parentLeftTuple,
+ MarshallerReaderContext context) throws IOException,
+ ClassNotFoundException {
+ ObjectInputStream stream = context.stream;
+ Map<Integer, BaseNode> sinks = context.sinks;
+
+ LeftTupleSink sink = parentLeftTuple.getLeftTupleSink();
+
+ switch ( sink.getType() ) {
+ case NodeTypeEnums.JoinNode : {
+ BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
+ addToLeftMemory(parentLeftTuple, memory);
+
+ while ( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ int factHandleId = stream.readInt();
+ RightTupleKey key = new RightTupleKey( factHandleId,
+ sink );
+ RightTuple rightTuple = context.rightTuples.get( key );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ rightTuple,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ }
+ break;
+
+ }
+ case NodeTypeEnums.EvalConditionNode : {
+ while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ }
+ break;
+ }
+ case NodeTypeEnums.NotNode :
+ case NodeTypeEnums.ForallNotNode : {
+ BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
+ int type = stream.readShort();
+ if ( type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED ) {
+ addToLeftMemory(parentLeftTuple, memory);
+
+ while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ }
+
+ } else {
+ int factHandleId = stream.readInt();
+ RightTupleKey key = new RightTupleKey( factHandleId,
+ sink );
+ RightTuple rightTuple = context.rightTuples.get( key );
+
+ parentLeftTuple.setBlocker( rightTuple );
+ rightTuple.addBlocked( parentLeftTuple );
+ }
+ break;
+ }
+ case NodeTypeEnums.ExistsNode : {
+ BetaMemory memory = (BetaMemory) context.wm.getNodeMemory( (BetaNode) sink );
+ int type = stream.readShort();
+ if ( type == PersisterEnums.LEFT_TUPLE_NOT_BLOCKED ) {
+ addToLeftMemory(parentLeftTuple, memory);
+ } else {
+ int factHandleId = stream.readInt();
+ RightTupleKey key = new RightTupleKey( factHandleId,
+ sink );
+ RightTuple rightTuple = context.rightTuples.get( key );
+
+ parentLeftTuple.setBlocker( rightTuple );
+ rightTuple.addBlocked( parentLeftTuple );
+
+ while ( stream.readShort() == PersisterEnums.LEFT_TUPLE ) {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ }
+ }
+ break;
+ }
+ case NodeTypeEnums.AccumulateNode : {
+ // accumulate nodes generate new facts on-demand and need special procedures when de-serializing from persistent storage
+ AccumulateMemory memory = (AccumulateMemory) context.wm.getNodeMemory( (BetaNode) sink );
+ memory.betaMemory.getLeftTupleMemory().add( parentLeftTuple );
+
+ AccumulateContext accctx = new AccumulateContext();
+ memory.betaMemory.getCreatedHandles().put( parentLeftTuple,
+ accctx,
+ false );
+ // first we de-serialize the generated fact handle
+ InternalFactHandle handle = readFactHandle( context );
+ accctx.result = new RightTuple( handle,
+ (RightTupleSink) sink );
+
+ // then we de-serialize the associated accumulation context
+ accctx.context = (Serializable) stream.readObject();
+ // then we de-serialize the boolean propagated flag
+ accctx.propagated = stream.readBoolean();
+
+ // then we de-serialize all the propagated tuples
+ short head = -1;
+ while ( (head = stream.readShort()) != PersisterEnums.END ) {
+ switch ( head ) {
+ case PersisterEnums.RIGHT_TUPLE : {
+ int factHandleId = stream.readInt();
+ RightTupleKey key = new RightTupleKey( factHandleId,
+ sink );
+ RightTuple rightTuple = context.rightTuples.get( key );
+ // just wiring up the match record
+ new LeftTuple( parentLeftTuple,
+ rightTuple,
+ sink,
+ true );
+
+ break;
+ }
+ case PersisterEnums.LEFT_TUPLE : {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ accctx.result,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ break;
+ }
+ default : {
+ throw new RuntimeDroolsException( "Marshalling error. This is a bug. Please contact the development team." );
+ }
+ }
+ }
+ break;
+ }
+ case NodeTypeEnums.RightInputAdaterNode : {
+ // RIANs generate new fact handles on-demand to wrap tuples and need special procedures when de-serializing from persistent storage
+ ObjectHashMap memory = (ObjectHashMap) context.wm.getNodeMemory( (NodeMemory) sink );
+ // create fact handle
+ int id = stream.readInt();
+ long recency = stream.readLong();
+ InternalFactHandle handle = new DefaultFactHandle( id,
+ parentLeftTuple,
+ recency,
+ context.wm.getEntryPoints().get( EntryPoint.DEFAULT.getEntryPointId() ) );
+ memory.put( parentLeftTuple, handle );
+
+ readRightTuples( handle, context );
+
+ stream.readShort(); // Persistence.END
+ break;
+ }
+ case NodeTypeEnums.FromNode: {
+// context.out.println( "FromNode" );
+ // FNs generate new fact handles on-demand to wrap objects and need special procedures when serializing to persistent storage
+ FromMemory memory = (FromMemory) context.wm.getNodeMemory( (NodeMemory) sink );
+
+ memory.betaMemory.getLeftTupleMemory().add( parentLeftTuple );
+ Map<Object, RightTuple> matches = new LinkedHashMap<Object, RightTuple>();
+ memory.betaMemory.getCreatedHandles().put( parentLeftTuple, matches );
+
+ while( stream.readShort() == PersisterEnums.FACT_HANDLE ) {
+ // we de-serialize the generated fact handle ID
+ InternalFactHandle handle = readFactHandle( context );
+ context.handles.put( handle.getId(),
+ handle );
+ readRightTuples( handle,
+ context );
+ matches.put( handle.getObject(), handle.getFirstRightTuple() );
+ }
+ while( stream.readShort() == PersisterEnums.RIGHT_TUPLE ) {
+ LeftTupleSink childSink = (LeftTupleSink) sinks.get( stream.readInt() );
+ int factHandleId = stream.readInt();
+ RightTupleKey key = new RightTupleKey( factHandleId,
+ null ); // created tuples in from node always use null sink
+ RightTuple rightTuple = context.rightTuples.get( key );
+ LeftTuple childLeftTuple = new LeftTuple( parentLeftTuple,
+ rightTuple,
+ childSink,
+ true );
+ readLeftTuple( childLeftTuple,
+ context );
+ }
+// context.out.println( "FromNode --- END" );
+ break;
+ }
+ case NodeTypeEnums.RuleTerminalNode : {
+ int pos = context.terminalTupleMap.size();
+ context.terminalTupleMap.put( pos,
+ parentLeftTuple );
+ break;
+ }
+ }
+ }
+
+ private static void addToLeftMemory(LeftTuple parentLeftTuple,
+ BetaMemory memory) {
+ memory.getLeftTupleMemory().add( parentLeftTuple );
+ memory.linkRight();
+ }
+
+ public static void readActivations(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+
+ while ( stream.readShort() == PersisterEnums.ACTIVATION ) {
+ readActivation( context );
+ }
+ }
+
+ public static Activation readActivation(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+ InternalRuleBase ruleBase = context.ruleBase;
+ InternalWorkingMemory wm = context.wm;
+
+ long activationNumber = stream.readLong();
+
+ int pos = stream.readInt();
+ LeftTuple leftTuple = context.terminalTupleMap.get( pos );
+
+ int salience = stream.readInt();
+
+ //PropagationContext context,
+ String pkgName = stream.readUTF();
+ String ruleName = stream.readUTF();
+ Package pkg = ruleBase.getPackage( pkgName );
+ Rule rule = pkg.getRule( ruleName );
+
+ RuleTerminalNode ruleTerminalNode = (RuleTerminalNode) leftTuple.getLeftTupleSink();
+ GroupElement subRule = ruleTerminalNode.getSubRule();
+
+ PropagationContext pc = context.propagationContexts.get( stream.readLong() );
+
+ AgendaItem activation = new AgendaItem( activationNumber,
+ leftTuple,
+ salience,
+ pc,
+ rule,
+ subRule );
+
+ leftTuple.setObject( activation );
+
+ if ( stream.readBoolean() ) {
+ String activationGroupName = stream.readUTF();
+ ((DefaultAgenda) wm.getAgenda()).getActivationGroup( activationGroupName ).addActivation( activation );
+ }
+
+ boolean activated = stream.readBoolean();
+ activation.setActivated( activated );
+
+ InternalAgendaGroup agendaGroup;
+ if ( rule.getAgendaGroup() == null || rule.getAgendaGroup().equals( "" ) || rule.getAgendaGroup().equals( AgendaGroup.MAIN ) ) {
+ // Is the Rule AgendaGroup undefined? If it is use MAIN,
+ // which is added to the Agenda by default
+ agendaGroup = (InternalAgendaGroup) ((DefaultAgenda) wm.getAgenda()).getAgendaGroup( AgendaGroup.MAIN );
+ } else {
+ // AgendaGroup is defined, so try and get the AgendaGroup
+ // from the Agenda
+ agendaGroup = (InternalAgendaGroup) ((DefaultAgenda) wm.getAgenda()).getAgendaGroup( rule.getAgendaGroup() );
+ }
+
+ activation.setAgendaGroup( agendaGroup );
+
+ if ( activated ) {
+ if ( rule.getRuleFlowGroup() == null ) {
+ agendaGroup.add( activation );
+ } else {
+ InternalRuleFlowGroup rfg = (InternalRuleFlowGroup) ((DefaultAgenda) wm.getAgenda()).getRuleFlowGroup( rule.getRuleFlowGroup() );
+ rfg.addActivation( activation );
+ }
+ }
+
+ TruthMaintenanceSystem tms = context.wm.getTruthMaintenanceSystem();
+ while ( stream.readShort() == PersisterEnums.LOGICAL_DEPENDENCY ) {
+ int factHandleId = stream.readInt();
+ InternalFactHandle handle = (InternalFactHandle) context.handles.get( factHandleId );
+ tms.addLogicalDependency( handle,
+ activation,
+ pc,
+ rule );
+ }
+
+ return activation;
+ }
+
+ public static void readPropagationContexts(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+
+ while ( stream.readShort() == PersisterEnums.PROPAGATION_CONTEXT ) {
+ readPropagationContext( context );
+ }
+
+ }
+
+ public static void readPropagationContext(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+ InternalRuleBase ruleBase = context.ruleBase;
+
+ int type = stream.readInt();
+
+ Rule rule = null;
+ if ( stream.readBoolean() ) {
+ String pkgName = stream.readUTF();
+ String ruleName = stream.readUTF();
+ Package pkg = ruleBase.getPackage( pkgName );
+ rule = pkg.getRule( ruleName );
+ }
+
+ LeftTuple leftTuple = null;
+ if ( stream.readBoolean() ) {
+ int tuplePos = stream.readInt();
+ leftTuple = (LeftTuple) context.terminalTupleMap.get( tuplePos );
+ }
+
+ long propagationNumber = stream.readLong();
+
+ int factHandleId = stream.readInt();
+ InternalFactHandle factHandle = context.handles.get( factHandleId );
+
+ int activeActivations = stream.readInt();
+ int dormantActivations = stream.readInt();
+ String entryPointId = stream.readUTF();
+
+ EntryPoint entryPoint = context.entryPoints.get( entryPointId );
+ if ( entryPoint == null ) {
+ entryPoint = new EntryPoint( entryPointId );
+ context.entryPoints.put( entryPointId,
+ entryPoint );
+ }
+
+ PropagationContext pc = new PropagationContextImpl( propagationNumber,
+ type,
+ rule,
+ leftTuple,
+ factHandle,
+ activeActivations,
+ dormantActivations,
+ entryPoint );
+ context.propagationContexts.put( propagationNumber,
+ pc );
+ }
+
+ public static WorkItem readWorkItem(MarshallerReaderContext context) throws IOException {
+ ObjectInputStream stream = context.stream;
+
+ WorkItemImpl workItem = new WorkItemImpl();
+ workItem.setId( stream.readLong() );
+ workItem.setProcessInstanceId( stream.readLong() );
+ workItem.setName( stream.readUTF() );
+ workItem.setState( stream.readInt() );
+
+ //WorkItem Paramaters
+ int nbVariables = stream.readInt();
+ if (nbVariables > 0) {
+
+ for (int i = 0; i < nbVariables; i++) {
+ String name = stream.readUTF();
+ try {
+ int index = stream.readInt();
+ ObjectMarshallingStrategy strategy = context.resolverStrategyFactory.getStrategy(index);
+
+ Object value = strategy.read(stream);
+ workItem.setParameter(name, value);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Could not reload variable " + name);
+ }
+ }
+ }
+
+
+
+
+ return workItem;
+ }
+
+
+
+}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/AbstractObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/AbstractObjectSinkAdapter.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/AbstractObjectSinkAdapter.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -21,6 +21,8 @@
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.common.NodeMemory;
import org.drools.common.RuleBasePartitionId;
/**
@@ -60,4 +62,5 @@
public void setPartitionId( RuleBasePartitionId partitionId ) {
this.partitionId = partitionId;
}
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaMemory.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -24,36 +24,39 @@
import org.drools.core.util.ObjectHashMap;
import org.drools.rule.ContextEntry;
-public class BetaMemory
- implements
- Externalizable {
+public class BetaMemory implements Externalizable, Unlinkable {
private static final long serialVersionUID = 510l;
- private LeftTupleMemory leftTupleMemory;
- private RightTupleMemory rightTupleMemory;
- private ObjectHashMap createdHandles;
- private ContextEntry[] context;
- private Object behaviorContext;
+ private LeftTupleMemory leftTupleMemory;
+ private RightTupleMemory rightTupleMemory;
+ private ObjectHashMap createdHandles;
+ private ContextEntry[] context;
+ private Object behaviorContext;
+
+ /* Let's start with only left unlinked. */
+ private boolean isLeftUnlinked = false;
+ private boolean isRightUnlinked = true;
public BetaMemory() {
}
public BetaMemory(final LeftTupleMemory tupleMemory,
- final RightTupleMemory objectMemory,
- final ContextEntry[] context) {
+ final RightTupleMemory objectMemory, final ContextEntry[] context) {
this.leftTupleMemory = tupleMemory;
this.rightTupleMemory = objectMemory;
this.context = context;
}
public void readExternal(ObjectInput in) throws IOException,
- ClassNotFoundException {
+ ClassNotFoundException {
leftTupleMemory = (LeftTupleMemory) in.readObject();
rightTupleMemory = (RightTupleMemory) in.readObject();
createdHandles = (ObjectHashMap) in.readObject();
context = (ContextEntry[]) in.readObject();
behaviorContext = (Object) in.readObject();
+ isLeftUnlinked = in.readBoolean();
+ isRightUnlinked = in.readBoolean();
}
public void writeExternal(ObjectOutput out) throws IOException {
@@ -62,6 +65,8 @@
out.writeObject( createdHandles );
out.writeObject( context );
out.writeObject( behaviorContext );
+ out.writeBoolean( isLeftUnlinked );
+ out.writeBoolean( isRightUnlinked );
}
public RightTupleMemory getRightTupleMemory() {
@@ -73,7 +78,7 @@
}
public ObjectHashMap getCreatedHandles() {
- if ( this.createdHandles == null ) {
+ if (this.createdHandles == null) {
this.createdHandles = new ObjectHashMap();
}
return this.createdHandles;
@@ -93,4 +98,29 @@
public void setBehaviorContext(Object behaviorContext) {
this.behaviorContext = behaviorContext;
}
+
+ public boolean isLeftUnlinked() {
+ return this.isLeftUnlinked;
+ }
+
+ public boolean isRightUnlinked() {
+ return this.isRightUnlinked;
+ }
+
+ public void linkLeft() {
+ this.isLeftUnlinked = false;
+ }
+
+ public void linkRight() {
+ this.isRightUnlinked = false;
+ }
+
+ public void unlinkLeft() {
+ this.isLeftUnlinked = true;
+ }
+
+ public void unlinkRight() {
+ this.isRightUnlinked = true;
+ }
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaNode.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaNode.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/BetaNode.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -23,6 +23,7 @@
import java.util.List;
import org.drools.RuleBaseConfiguration;
+import org.drools.builder.conf.LRUnlinkingOption;
import org.drools.common.BaseNode;
import org.drools.common.BetaConstraints;
import org.drools.common.InternalFactHandle;
@@ -81,6 +82,9 @@
protected boolean objectMemory = true; // hard coded to true
protected boolean tupleMemoryEnabled;
protected boolean concurrentRightTupleMemory = false;
+
+ /** @see LRUnlinkingOption */
+ protected boolean lrUnlinkingEnabled = false;
// ------------------------------------------------------------
// Constructors
@@ -113,7 +117,7 @@
this.behavior = new BehaviorManager( behaviors );
if ( this.constraints == null ) {
- throw new RuntimeException( "cannot have null constraints, must at least be an instance of EmptyBetaConstraints" );
+ throw new IllegalStateException( "cannot have null constraints, must at least be an instance of EmptyBetaConstraints" );
}
}
@@ -130,6 +134,7 @@
objectMemory = in.readBoolean();
tupleMemoryEnabled = in.readBoolean();
concurrentRightTupleMemory = in.readBoolean();
+ lrUnlinkingEnabled = in.readBoolean();
super.readExternal( in );
}
@@ -146,6 +151,7 @@
out.writeBoolean( objectMemory );
out.writeBoolean( tupleMemoryEnabled );
out.writeBoolean( concurrentRightTupleMemory );
+ out.writeBoolean( lrUnlinkingEnabled );
super.writeExternal( out );
}
@@ -211,9 +217,19 @@
null,
null,
null );
- this.rightInput.updateSink( this,
- propagationContext,
- workingMemory );
+
+ /* When L&R Unlinking is enabled, we only need to update the side
+ * that is initially linked. If there are tuples to be propagated,
+ * they will trigger the update (thus, population) of the other side.
+ * */
+ if (!lrUnlinkingEnabled ||
+ (lrUnlinkingEnabled && !(this instanceof JoinNode) )) {
+
+ this.rightInput.updateSink( this,
+ propagationContext,
+ workingMemory );
+ }
+
this.leftInput.updateSink( this,
propagationContext,
workingMemory );
@@ -300,6 +316,7 @@
ModifyPreviousTuples modifyPreviousTuples,
PropagationContext context,
InternalWorkingMemory workingMemory) {
+
RightTuple rightTuple = modifyPreviousTuples.removeRightTuple( this );
if ( rightTuple != null ) {
rightTuple.reAdd();
@@ -319,6 +336,7 @@
ModifyPreviousTuples modifyPreviousTuples,
PropagationContext context,
InternalWorkingMemory workingMemory) {
+
LeftTuple leftTuple = modifyPreviousTuples.removeLeftTuple( this );
if ( leftTuple != null ) {
leftTuple.reAdd(); //
@@ -485,4 +503,39 @@
}
}
+ protected boolean leftUnlinked(final PropagationContext context,
+ final InternalWorkingMemory workingMemory, final BetaMemory memory) {
+
+ // If left input is unlinked, don't do anything.
+ if(memory.isLeftUnlinked()) {
+ return true;
+ }
+
+ if (memory.isRightUnlinked()) {
+ memory.linkRight();
+ // updates the right input memory before going on.
+ this.rightInput.updateSink(this, context, workingMemory);
+ }
+
+ return false;
+ }
+
+ protected boolean rightUnlinked(final PropagationContext context,
+ final InternalWorkingMemory workingMemory, final BetaMemory memory) {
+
+ if (memory.isRightUnlinked()) {
+ return true;
+ }
+
+ if (memory.isLeftUnlinked()) {
+
+ memory.linkLeft();
+ // updates the left input memory before going on.
+ this.leftInput.updateSink(this, context, workingMemory);
+ }
+
+ return false;
+ }
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/CompositeObjectSinkAdapter.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -338,6 +338,7 @@
public void propagateAssertObject(final InternalFactHandle factHandle,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
final Object object = factHandle.getObject();
// Iterates the FieldIndex collection, which tells you if particularly field is hashed or not
@@ -447,6 +448,7 @@
PropagationContext context,
InternalWorkingMemory workingMemory,
ObjectSink sink) {
+
sink.assertObject( factHandle,
context,
workingMemory );
@@ -520,7 +522,10 @@
public int size() {
return (this.otherSinks != null ? this.otherSinks.size() : 0) + (this.hashableSinks != null ? this.hashableSinks.size() : 0) + (this.hashedSinkMap != null ? this.hashedSinkMap.size() : 0);
}
+
+
+
public static class HashKey
implements
Externalizable {
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/EmptyObjectSinkAdapter.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -95,5 +95,12 @@
}
+ public boolean shouldPropagate(InternalWorkingMemory workingMemory) {
+ return true;
+ }
+
+
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/JoinNode.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/JoinNode.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/JoinNode.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -53,14 +53,26 @@
binder,
behaviors );
this.tupleMemoryEnabled = context.isTupleMemoryEnabled();
+ this.lrUnlinkingEnabled = context.getRuleBase().getConfiguration().isLRUnlinkingEnabled();
}
public void assertLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+ if(lrUnlinkingEnabled &&
+ leftUnlinked(context,
+ workingMemory,
+ memory)) {
+ return;
+ }
+
+
boolean useLeftMemory = true;
+
if ( this.tupleMemoryEnabled ) {
memory.getLeftTupleMemory().add( leftTuple );
} else {
@@ -98,8 +110,18 @@
public void assertObject(final InternalFactHandle factHandle,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+ if (lrUnlinkingEnabled &&
+ rightUnlinked(context,
+ workingMemory,
+ memory)) {
+ context.setLatestPropagationAttempt();
+ return;
+ }
+
+
RightTuple rightTuple = createRightTuple( factHandle,
this );
@@ -121,6 +143,8 @@
workingMemory,
factHandle );
int i = 0;
+
+ // TODO lgomes: Do I really need to propagate when I know that the sink is an EmptyLeftTupleSinkAdapter
for ( LeftTuple leftTuple = memory.getLeftTupleMemory().getFirst( rightTuple ); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getNext() ) {
if ( this.constraints.isAllowedCachedRight( memory.getContext(),
leftTuple ) ) {
@@ -138,14 +162,25 @@
this.constraints.resetFactHandle( memory.getContext() );
}
+
public void retractRightTuple(final RightTuple rightTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+ if (lrUnlinkingEnabled &&
+ memory.isRightUnlinked()) {
+ return;
+ }
+
behavior.retractRightTuple( memory.getBehaviorContext(),
- rightTuple,
- workingMemory );
+ rightTuple,
+ workingMemory );
+
memory.getRightTupleMemory().remove( rightTuple );
+
+ // Check if memory should be unlinked
+ //checkLeftUnlinking(memory);
if ( rightTuple.firstChild != null ) {
this.sink.propagateRetractRightTuple( rightTuple,
@@ -154,11 +189,24 @@
}
}
+
public void retractLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
+
+ if (lrUnlinkingEnabled &&
+ memory.isLeftUnlinked()) {
+ return;
+ }
+
memory.getLeftTupleMemory().remove( leftTuple );
+
+ // Check if right side should be unlinked.
+ //checkRightUnlinking(memory);
+
+
if ( leftTuple.firstChild != null ) {
this.sink.propagateRetractLeftTuple( leftTuple,
context,
@@ -170,7 +218,7 @@
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
+
// WTD here
// if ( !behavior.assertRightTuple( memory.getBehaviorContext(),
// rightTuple,
@@ -268,8 +316,9 @@
public void modifyLeftTuple(final LeftTuple leftTuple,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
-
+
// 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
memory.getLeftTupleMemory().remove( leftTuple );
@@ -359,7 +408,7 @@
public void updateSink(final LeftTupleSink sink,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
-
+
final BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory( this );
final Iterator tupleIter = memory.getLeftTupleMemory().iterator();
@@ -369,8 +418,10 @@
leftTuple );
for ( RightTuple rightTuple = memory.getRightTupleMemory().getFirst( leftTuple,
(InternalFactHandle) context.getFactHandle() ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
- if ( this.constraints.isAllowedCachedLeft( memory.getContext(),
+
+ if (this.constraints.isAllowedCachedLeft( memory.getContext(),
rightTuple.getFactHandle() ) ) {
+
sink.assertLeftTuple( new LeftTuple( leftTuple,
rightTuple,
null,
@@ -385,7 +436,7 @@
this.constraints.resetTuple( memory.getContext() );
}
}
-
+
public short getType() {
return NodeTypeEnums.JoinNode;
}
@@ -398,4 +449,35 @@
return "[JoinNode(" + this.getId() + ") - " + ((ObjectTypeNode) source).getObjectType() + "]";
}
+
+ @Override
+ public void modifyLeftTuple(InternalFactHandle factHandle,
+ ModifyPreviousTuples modifyPreviousTuples,
+ PropagationContext context, InternalWorkingMemory workingMemory) {
+
+ BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this);
+
+ if (lrUnlinkingEnabled &&
+ memory.isLeftUnlinked())
+ return;
+
+ super.modifyLeftTuple(factHandle, modifyPreviousTuples, context, workingMemory);
+ }
+
+ @Override
+ public void modifyObject(InternalFactHandle factHandle,
+ ModifyPreviousTuples modifyPreviousTuples,
+ PropagationContext context, InternalWorkingMemory workingMemory) {
+
+
+ BetaMemory memory = (BetaMemory) workingMemory.getNodeMemory(this);
+
+ if (lrUnlinkingEnabled &&
+ memory.isRightUnlinked())
+ return;
+
+ super.modifyObject(factHandle, modifyPreviousTuples, context, workingMemory);
+ }
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTuple.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -18,12 +18,10 @@
import java.util.Arrays;
-import org.drools.common.AgendaItem;
import org.drools.common.InternalFactHandle;
import org.drools.core.util.Entry;
import org.drools.core.util.LeftTupleList;
import org.drools.rule.Declaration;
-import org.drools.spi.Activation;
import org.drools.spi.Tuple;
public class LeftTuple
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/LeftTupleMemory.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -39,5 +39,7 @@
// public Entry[] getTable();
public Entry[] toArray();
+
+ public void clear();
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectSinkPropagator.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -44,5 +44,5 @@
ModifyPreviousTuples modifyPreviousTuples,
PropagationContext context,
InternalWorkingMemory workingMemory);
-
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/ObjectTypeNode.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -24,6 +24,7 @@
import org.drools.RuleBaseConfiguration;
import org.drools.base.ClassObjectType;
import org.drools.base.ValueType;
+import org.drools.builder.conf.LRUnlinkingOption;
import org.drools.common.AbstractRuleBase;
import org.drools.common.BaseNode;
import org.drools.common.DroolsObjectInputStream;
@@ -97,7 +98,15 @@
private transient ExpireJob job = new ExpireJob();
private CompiledNetwork compiledNetwork;
-
+
+ /** When L&R Unlinking is active, updateSink() may be recursively
+ * called during propagation and we need to keep track of the
+ * fact that we are propagating. */
+ private boolean isPropagating = false;
+
+ /** @see LRUnlinkingOption */
+ private boolean lrUnlinkingEnabled = false;
+
public ObjectTypeNode() {
}
@@ -119,6 +128,7 @@
source,
context.getRuleBase().getConfiguration().getAlphaNodeHashingThreshold() );
this.objectType = objectType;
+ this.lrUnlinkingEnabled = context.getRuleBase().getConfiguration().isLRUnlinkingEnabled();
setObjectMemoryEnabled( context.isObjectTypeNodeMemoryEnabled() );
}
@@ -136,6 +146,7 @@
skipOnModify = in.readBoolean();
objectMemoryEnabled = in.readBoolean();
expirationOffset = in.readLong();
+ lrUnlinkingEnabled = in.readBoolean();
}
public void writeExternal(ObjectOutput out) throws IOException {
@@ -144,6 +155,7 @@
out.writeBoolean( skipOnModify );
out.writeBoolean( objectMemoryEnabled );
out.writeLong( expirationOffset );
+ out.writeBoolean( lrUnlinkingEnabled );
}
/**
@@ -177,6 +189,7 @@
public void assertObject(final InternalFactHandle factHandle,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
if ( this.objectMemoryEnabled ) {
final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory( this );
memory.add( factHandle,
@@ -187,9 +200,10 @@
context,
workingMemory );
} else {
- this.sink.propagateAssertObject( factHandle,
- context,
- workingMemory );
+
+ doPropagateAssertObject( factHandle,
+ context,
+ workingMemory);
}
if ( this.expirationOffset >= 0 && this.expirationOffset != Long.MAX_VALUE ) {
@@ -212,6 +226,18 @@
}
+ private void doPropagateAssertObject(final InternalFactHandle factHandle,
+ final PropagationContext context,
+ final InternalWorkingMemory workingMemory) {
+
+ isPropagating = true;
+
+ this.sink.propagateAssertObject( factHandle,
+ context,
+ workingMemory );
+ isPropagating = false;
+ }
+
/**
* Retract the <code>FactHandleimpl</code> from the <code>Rete</code> network. Also remove the
* <code>FactHandleImpl</code> from the node memory.
@@ -270,15 +296,68 @@
public void updateSink(final ObjectSink sink,
final PropagationContext context,
final InternalWorkingMemory workingMemory) {
+
+ if (lrUnlinkingEnabled) {
+ // Update sink taking into account L&R unlinking peculiarities
+ updateLRUnlinking(sink, context, workingMemory);
+
+ } else {
+ // Regular updateSink
+ final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory( this );
+ Iterator it = memory.iterator();
+
+ for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+ sink.assertObject( (InternalFactHandle) entry.getValue(),
+ context,
+ workingMemory );
+ }
+ }
+
+ }
+
+ /**
+ * When L&R Unlinking is enabled, updateSink() is used to populate
+ * a node's memory, but it has to take into account if it's propagating.
+ */
+ private void updateLRUnlinking(final ObjectSink sink,
+ final PropagationContext context,
+ final InternalWorkingMemory workingMemory) {
+
final ObjectHashSet memory = (ObjectHashSet) workingMemory.getNodeMemory( this );
+
Iterator it = memory.iterator();
- for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
- sink.assertObject( (InternalFactHandle) entry.getValue(),
- context,
- workingMemory );
+
+
+ InternalFactHandle ctxHandle = (InternalFactHandle)context.getFactHandle();
+
+ if (!isPropagating ||
+ (isPropagating && context.getLatestPropagationAttempt() == ctxHandle.getId())){
+
+ context.resetLatestPropagationAttempt();
+
+ for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+ // Assert everything
+ sink.assertObject( (InternalFactHandle) entry.getValue(),
+ context,
+ workingMemory );
+ }
+
+ } else {
+
+ for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
+ InternalFactHandle handle = (InternalFactHandle) entry.getValue();
+ // Exclude the current fact propagation
+ if (handle.getId() != ctxHandle.getId()) {
+ sink.assertObject( handle,
+ context,
+ workingMemory );
+ }
+ }
}
}
+
+
/**
* Rete needs to know that this ObjectTypeNode has been added
*/
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/RightTupleMemory.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -38,4 +38,6 @@
public Entry[] toArray();
public int size();
+
+ public void clear();
}
Added: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/Unlinkable.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/Unlinkable.java (rev 0)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/reteoo/Unlinkable.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -0,0 +1,39 @@
+/**
+ * Copyright 2010 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.reteoo;
+
+/**
+ * A marker interface to specify unlinkable node memories.
+ *
+ * @author lgomes
+ */
+public interface Unlinkable {
+
+ /** Whether or not the left side is unlinked. */
+ boolean isLeftUnlinked();
+
+ /** Whether or not the right side is unlinked. */
+ boolean isRightUnlinked();
+
+ void linkLeft();
+
+ void linkRight();
+
+ void unlinkLeft();
+
+ void unlinkRight();
+
+}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/spi/PropagationContext.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/spi/PropagationContext.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/main/java/org/drools/spi/PropagationContext.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -59,5 +59,8 @@
public EntryPoint getEntryPoint();
+ public int getLatestPropagationAttempt();
+ public void setLatestPropagationAttempt();
+ public void resetLatestPropagationAttempt();
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/RuleBaseConfigurationTest.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/RuleBaseConfigurationTest.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/RuleBaseConfigurationTest.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -113,4 +113,20 @@
assertTrue( cfg.getAgendaGroupFactory() instanceof PriorityQueueAgendaGroupFactory );
}
+ public void testLRUnlinking() {
+ RuleBaseConfiguration cfg = new RuleBaseConfiguration();
+ assertEquals( false,
+ cfg.isLRUnlinkingEnabled() );
+
+ Properties properties = new Properties();
+ properties.setProperty( "drools.lrUnlinkingEnabled",
+ "true" );
+ cfg = new RuleBaseConfiguration( properties );
+
+ assertEquals( true,
+ cfg.isLRUnlinkingEnabled() );
+ }
+
+
+
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/MockObjectSource.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -78,6 +78,10 @@
public void addFact(final InternalFactHandle handle) {
this.facts.add( handle );
}
+
+ public void removeFact(final InternalFactHandle handle) {
+ this.facts.remove( handle );
+ }
public void updateSink(final ObjectSink sink,
final PropagationContext context,
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/ObjectTypeNodeTest.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -343,7 +343,7 @@
sink2.getAsserted().size() );
objectTypeNode.updateSink( sink2,
- null,
+ new PropagationContextImpl(),
workingMemory );
assertEquals( 2,
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/JUnitNodeTestRunner.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/JUnitNodeTestRunner.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/JUnitNodeTestRunner.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -20,8 +20,8 @@
import java.util.List;
import org.drools.RuntimeDroolsException;
+import org.drools.reteoo.test.dsl.NodeTestCase;
import org.drools.reteoo.test.dsl.NodeTestDef;
-import org.drools.reteoo.test.dsl.NodeTestCase;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
@@ -34,33 +34,40 @@
public class JUnitNodeTestRunner extends Runner {
// The description of the test suite
- private Description descr;
+ private Description descr;
private List<NodeTestCase> testCases = new ArrayList<NodeTestCase>();
- public JUnitNodeTestRunner(Class< ? > clazz) {
+ public JUnitNodeTestRunner(Class<?> clazz) {
try {
- NodeTestCasesSource ntsuite = (NodeTestCasesSource) clazz.newInstance();
+ NodeTestCasesSource ntsuite = (NodeTestCasesSource) clazz
+ .newInstance();
testCases = ntsuite.getTestCases();
- } catch ( Exception e ) {
+ } catch (Exception e) {
e.printStackTrace();
- throw new RuntimeDroolsException( "Error instantiating node test runner: "+e, e );
+ throw new RuntimeDroolsException(
+ "Error instantiating node test runner: " + e, e);
}
- this.descr = Description.createSuiteDescription( "Node test case suite" );
+ this.descr = Description.createSuiteDescription("Node test case suite");
- for ( NodeTestCase tcase : testCases ) {
- Description tcaseDescr = Description.createSuiteDescription( tcase.getName() );
- tcase.setDescription( tcaseDescr );
- this.descr.addChild( tcaseDescr );
- for ( NodeTestDef ntest : tcase.getTests() ) {
- Description ntestDescr = Description.createTestDescription( clazz,
- ntest.getName() );
- tcaseDescr.addChild( ntestDescr );
- ntest.setDescription( ntestDescr );
+ for (NodeTestCase tcase : testCases) {
+
+ Description tcaseDescr = Description.createSuiteDescription(tcase
+ .getFileName() != null ? tcase.getFileName() : tcase.getName());
+
+ tcase.setDescription(tcaseDescr);
+ this.descr.addChild(tcaseDescr);
+ for (NodeTestDef ntest : tcase.getTests()) {
+ Description ntestDescr = Description.createTestDescription(
+ clazz, ntest.getName());
+ tcaseDescr.addChild(ntestDescr);
+ ntest.setDescription(ntestDescr);
}
}
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see org.junit.runner.Runner#getDescription()
*/
@Override
@@ -68,16 +75,18 @@
return descr;
}
- /* (non-Javadoc)
- * @see org.junit.runner.Runner#run(org.junit.runner.notification.RunNotifier)
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.junit.runner.Runner#run(org.junit.runner.notification.RunNotifier)
*/
@Override
public void run(RunNotifier notifier) {
+
ReteDslTestEngine tester = new ReteDslTestEngine();
- for ( NodeTestCase tcase : testCases ) {
- tester.run( tcase,
- notifier );
+ for (NodeTestCase tcase : testCases) {
+ tester.run(tcase, notifier);
}
}
-
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/NodeSuiteTest.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/NodeSuiteTest.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/NodeSuiteTest.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -45,11 +45,12 @@
for ( File file : base.listFiles( new FilenameFilter() {
public boolean accept(File arg0,
String arg1) {
- return arg1.endsWith( ".nodeTestCase" );
+ return arg1.endsWith( NodeTestCase.SUFFIX );
}
} ) ) {
InputStream is = new FileInputStream( file );
NodeTestCase tcase = ReteDslTestEngine.compile( is );
+ tcase.setFileName(file.getName());
if ( tcase.hasErrors() ) {
throw new IllegalArgumentException( "Error parsing and loading testcase: " + file.getAbsolutePath() + "\n" + tcase.getErrors().toString() );
}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngine.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngine.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngine.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -22,11 +22,14 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import junit.framework.AssertionFailedError;
+
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.ANTLRReaderStream;
import org.antlr.runtime.ANTLRStringStream;
@@ -63,6 +66,7 @@
import org.drools.reteoo.test.dsl.AccumulateNodeStep;
import org.drools.reteoo.test.dsl.BetaNodeStep;
import org.drools.reteoo.test.dsl.BindingStep;
+import org.drools.reteoo.test.dsl.ConfigStep;
import org.drools.reteoo.test.dsl.DSLMock;
import org.drools.reteoo.test.dsl.DslStep;
import org.drools.reteoo.test.dsl.EvalNodeStep;
@@ -97,22 +101,26 @@
public class ReteDslTestEngine {
- private static final String OBJECT_TYPE_NODE = "ObjectTypeNode";
- private static final String LEFT_INPUT_ADAPTER_NODE = "LeftInputAdapterNode";
- private static final String BINDING = "Binding";
- private static final String JOIN_NODE = "JoinNode";
- private static final String NOT_NODE = "NotNode";
- private static final String EXISTS_NODE = "ExistsNode";
- private static final String ACCUMULATE_NODE = "AccumulateNode";
- private static final String RULE_TERMINAL_NODE = "RuleTerminalNode";
- private static final String EVAL_NODE = "EvalNode";
- private static final String WITH = "With";
- private static final String FACTS = "Facts";
+ public static final String WORKING_MEMORY = "WorkingMemory";
+ public static final String BUILD_CONTEXT = "BuildContext";
+
+ private static final String CONFIG = "Config";
+ private static final String OBJECT_TYPE_NODE = "ObjectTypeNode";
+ private static final String LEFT_INPUT_ADAPTER_NODE = "LeftInputAdapterNode";
+ private static final String BINDING = "Binding";
+ private static final String JOIN_NODE = "JoinNode";
+ private static final String NOT_NODE = "NotNode";
+ private static final String EXISTS_NODE = "ExistsNode";
+ private static final String ACCUMULATE_NODE = "AccumulateNode";
+ private static final String RULE_TERMINAL_NODE = "RuleTerminalNode";
+ private static final String EVAL_NODE = "EvalNode";
+ private static final String WITH = "With";
+ private static final String FACTS = "Facts";
private static final String RIGHT_INPUT_ADAPTER_NODE = "RightInputAdapterNode";
- private static final String LEFT_TUPLE_SINK_STEP = "LeftTupleSink";
- private static final String BETA_NODE_STEP = "BetaNodeStep";
+ private static final String LEFT_TUPLE_SINK_STEP = "LeftTupleSink";
+ private static final String BETA_NODE_STEP = "BetaNodeStep";
- private ReteTesterHelper reteTesterHelper;
+ private ReteTesterHelper reteTesterHelper;
private Map<String, Object> steps;
public ReteDslTestEngine() {
@@ -120,173 +128,160 @@
this.reteTesterHelper = new ReteTesterHelper();
this.steps = new HashMap<String, Object>();
-
- this.steps.put( OBJECT_TYPE_NODE,
- new ObjectTypeNodeStep( this.reteTesterHelper ) );
- this.steps.put( LEFT_INPUT_ADAPTER_NODE,
- new LeftInputAdapterNodeStep( this.reteTesterHelper ) );
- this.steps.put( BINDING,
- new BindingStep( this.reteTesterHelper ) );
- this.steps.put( JOIN_NODE,
- new JoinNodeStep( this.reteTesterHelper ) );
- this.steps.put( NOT_NODE,
- new NotNodeStep( this.reteTesterHelper ) );
- this.steps.put( EXISTS_NODE,
- new ExistsNodeStep( this.reteTesterHelper ) );
- this.steps.put( ACCUMULATE_NODE,
- new AccumulateNodeStep( this.reteTesterHelper ) );
- this.steps.put( RULE_TERMINAL_NODE,
- new RuleTerminalNodeStep( this.reteTesterHelper ) );
- this.steps.put( EVAL_NODE,
- new EvalNodeStep( this.reteTesterHelper ) );
- this.steps.put( RIGHT_INPUT_ADAPTER_NODE,
- new RIANodeStep( this.reteTesterHelper ) );
- this.steps.put( FACTS,
- new FactsStep( this.reteTesterHelper ) );
- this.steps.put( WITH,
- new WithStep( this.reteTesterHelper ) );
- this.steps.put( LEFT_TUPLE_SINK_STEP,
- new LeftTupleSinkStep( this.reteTesterHelper ) );
- this.steps.put( BETA_NODE_STEP,
- new BetaNodeStep( this.reteTesterHelper ) );
+
+ this.steps.put(CONFIG, new ConfigStep());
+ this.steps.put(OBJECT_TYPE_NODE, new ObjectTypeNodeStep(
+ this.reteTesterHelper));
+ this.steps.put(LEFT_INPUT_ADAPTER_NODE, new LeftInputAdapterNodeStep(
+ this.reteTesterHelper));
+ this.steps.put(BINDING, new BindingStep(this.reteTesterHelper));
+ this.steps.put(JOIN_NODE, new JoinNodeStep(this.reteTesterHelper));
+ this.steps.put(NOT_NODE, new NotNodeStep(this.reteTesterHelper));
+ this.steps.put(EXISTS_NODE, new ExistsNodeStep(this.reteTesterHelper));
+ this.steps.put(ACCUMULATE_NODE, new AccumulateNodeStep(
+ this.reteTesterHelper));
+ this.steps.put(RULE_TERMINAL_NODE, new RuleTerminalNodeStep(
+ this.reteTesterHelper));
+ this.steps.put(EVAL_NODE, new EvalNodeStep(this.reteTesterHelper));
+ this.steps.put(RIGHT_INPUT_ADAPTER_NODE, new RIANodeStep(
+ this.reteTesterHelper));
+ this.steps.put(FACTS, new FactsStep(this.reteTesterHelper));
+ this.steps.put(WITH, new WithStep(this.reteTesterHelper));
+ this.steps.put(LEFT_TUPLE_SINK_STEP, new LeftTupleSinkStep(
+ this.reteTesterHelper));
+ this.steps.put(BETA_NODE_STEP, new BetaNodeStep(this.reteTesterHelper));
}
- public NodeTestCaseResult run(NodeTestCase testCase,
- RunNotifier notifier) {
- if ( testCase == null || testCase.hasErrors() ) {
- throw new IllegalArgumentException( "Impossible to execute test case due to existing errors: " + testCase.getErrors() );
+ public NodeTestCaseResult run(NodeTestCase testCase, RunNotifier notifier) {
+ if (testCase == null || testCase.hasErrors()) {
+ throw new IllegalArgumentException(
+ "Impossible to execute test case due to existing errors: "
+ + testCase.getErrors());
}
- if ( notifier == null ) {
+ if (notifier == null) {
notifier = EmptyNotifier.INSTANCE;
}
- this.reteTesterHelper.addImports( testCase.getImports() );
- NodeTestCaseResult result = new NodeTestCaseResult( testCase );
- for ( NodeTestDef test : testCase.getTests() ) {
- notifier.fireTestStarted( test.getDescription() );
- NodeTestResult testResult = run( testCase,
- test );
- switch ( testResult.result ) {
- case SUCCESS :
- notifier.fireTestFinished( test.getDescription() );
+ this.reteTesterHelper.addImports(testCase.getImports());
+ NodeTestCaseResult result = new NodeTestCaseResult(testCase);
+
+ for (NodeTestDef test : testCase.getTests()) {
+
+ notifier.fireTestStarted(test.getDescription());
+ NodeTestResult testResult = createTestResult(test, null);
+
+ try {
+
+ testResult = run(testCase, test);
+
+ switch (testResult.result) {
+ case SUCCESS:
+ notifier.fireTestFinished(test.getDescription());
break;
- case ERROR :
- case FAILURE :
- notifier.fireTestFailure( new Failure( test.getDescription(),
- new AssertionError( testResult.errorMsgs ) ) );
+ case ERROR:
+ case FAILURE:
+ notifier.fireTestFailure(new Failure(test.getDescription(),
+ new AssertionError(testResult.errorMsgs)));
break;
+ }
+
+
+ } catch (Throwable e) {
+ notifier.fireTestFailure(new Failure(test.getDescription(), e));
}
- result.add( testResult );
+
+ result.add(testResult);
}
+
return result;
}
- private NodeTestResult run(NodeTestCase testCase,
- NodeTestDef test) {
- Map<String, Object> context = createContext( testCase );
- NodeTestResult result = new NodeTestResult( test,
- Result.NOT_EXECUTED,
- context,
- new LinkedList<String>() );
+ private NodeTestResult run(NodeTestCase testCase, NodeTestDef test) {
+ Map<String, Object> context = createContext(testCase);
+ NodeTestResult result = createTestResult(test, context);
+
try {
// run setup
- run( context,
- testCase.getSetup(),
- result );
+ run(context, testCase.getSetup(), result);
// run test
- run( context,
- test.getSteps(),
- result );
+ run(context, test.getSteps(), result);
// run tearDown
- run( context,
- testCase.getTearDown(),
- result );
+ run(context, testCase.getTearDown(), result);
result.result = Result.SUCCESS;
- } catch ( Exception e ) {
+ } catch (Throwable e) {
result.result = Result.ERROR;
- result.errorMsgs.add( e.getMessage() );
+ result.errorMsgs.add(e.toString());
}
return result;
}
+ private NodeTestResult createTestResult(NodeTestDef test,
+ Map<String, Object> context) {
+ NodeTestResult result = new NodeTestResult(test, Result.NOT_EXECUTED,
+ context, new LinkedList<String>());
+ return result;
+ }
+
private Map<String, Object> createContext(NodeTestCase testCase) {
Map<String, Object> context = new HashMap<String, Object>();
- context.put( "TestCase",
- testCase );
+ context.put("TestCase", testCase);
RuleBaseConfiguration conf = new RuleBaseConfiguration();
- ReteooRuleBase rbase = new ReteooRuleBase( "ID",
- conf );
- BuildContext buildContext = new BuildContext( rbase,
- rbase.getReteooBuilder().getIdGenerator() );
- context.put( "BuildContext",
- buildContext );
- context.put( "ClassFieldAccessorStore",
- this.reteTesterHelper.getStore() );
+ ReteooRuleBase rbase = new ReteooRuleBase("ID", conf);
+ BuildContext buildContext = new BuildContext(rbase, rbase
+ .getReteooBuilder().getIdGenerator());
+ context.put(BUILD_CONTEXT, buildContext);
+ context
+ .put("ClassFieldAccessorStore", this.reteTesterHelper
+ .getStore());
- InternalWorkingMemory wm = (InternalWorkingMemory) rbase.newStatefulSession( true );
- context.put( "WorkingMemory",
- wm );
+ InternalWorkingMemory wm = (InternalWorkingMemory) rbase
+ .newStatefulSession(true);
+ context.put(WORKING_MEMORY, wm);
return context;
}
public Map<String, Object> run(Map<String, Object> context,
- List<DslStep> steps,
- NodeTestResult result) {
- InternalWorkingMemory wm = (InternalWorkingMemory) context.get( "WorkingMemory" );
- for ( DslStep step : steps ) {
+ List<DslStep> steps, NodeTestResult result) {
+ InternalWorkingMemory wm = (InternalWorkingMemory) context
+ .get(WORKING_MEMORY);
+ for (DslStep step : steps) {
String name = step.getName();
- Object object = this.steps.get( name );
- if ( object != null && object instanceof Step ) {
+ Object object = this.steps.get(name);
+ if (object != null && object instanceof Step) {
Step stepImpl = (Step) object;
try {
- stepImpl.execute( context,
- step.getCommands() );
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ stepImpl.execute(context, step.getCommands());
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
- } else if ( "assert".equals( name.trim() ) ) {
- assertObject( step,
- context,
- wm );
- } else if ( "retract".equals( name.trim() ) ) {
- retractObject( step,
- context,
- wm );
- } else if ( "modify".equals( name.trim() ) ) {
- modifyObject( step,
- context,
- wm );
+ } else if ("assert".equals(name.trim())) {
+ assertObject(step, context, wm);
+ } else if ("retract".equals(name.trim())) {
+ retractObject(step, context, wm);
+ } else if ("modify".equals(name.trim())) {
+ modifyObject(step, context, wm);
} else {
- Object node = context.get( name.trim() );
- if ( node == null ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": step " + name + " does not exist" );
+ Object node = context.get(name.trim());
+ if (node == null) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": step " + name + " does not exist");
}
- if ( node instanceof DSLMock ) {
+ if (node instanceof DSLMock) {
// it is a mock
- MockitoHelper.process( step,
- (LeftTupleSink) node,
- context,
- wm );
- } else if ( node instanceof BetaNode ) {
- betaNode( step,
- (BetaNode) node,
- context,
- wm );
- } else if ( node instanceof RightInputAdapterNode ) {
- riaNode( step,
- (RightInputAdapterNode) node,
- context,
- wm );
- } else if ( node instanceof RuleTerminalNode ) {
- ruleTerminalNode( step,
- (RuleTerminalNode) node,
- context,
- wm );
+ MockitoHelper.process(step, (LeftTupleSink) node, context,
+ wm);
+ } else if (node instanceof BetaNode) {
+ betaNode(step, (BetaNode) node, context, wm);
+ } else if (node instanceof RightInputAdapterNode) {
+ riaNode(step, (RightInputAdapterNode) node, context, wm);
+ } else if (node instanceof RuleTerminalNode) {
+ ruleTerminalNode(step, (RuleTerminalNode) node, context, wm);
} else {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unknown node " + node );
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unknown node " + node);
}
}
}
@@ -294,523 +289,663 @@
return context;
}
- private void betaNode(DslStep step,
- BetaNode node,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private void betaNode(DslStep step, BetaNode node,
+ Map<String, Object> context, InternalWorkingMemory wm) {
+
+ final boolean lrUnlinkingEnabled = ((BuildContext) context.get(BUILD_CONTEXT))
+ .getRuleBase()
+ .getConfiguration().isLRUnlinkingEnabled();
+
try {
List<String[]> cmds = step.getCommands();
- List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
+ List<InternalFactHandle> handles = (List<InternalFactHandle>) context
+ .get("Handles");
BetaMemory memory = null;
- if ( node instanceof AccumulateNode ) {
- AccumulateMemory accmem = (AccumulateMemory) wm.getNodeMemory( node );
+ if (node instanceof AccumulateNode) {
+ AccumulateMemory accmem = (AccumulateMemory) wm
+ .getNodeMemory(node);
memory = accmem.betaMemory;
} else {
- memory = (BetaMemory) wm.getNodeMemory( node );
+ memory = (BetaMemory) wm.getNodeMemory(node);
}
- for ( String[] cmd : cmds ) {
- if ( cmd[0].equals( "leftMemory" ) ) {
+ for (String[] cmd : cmds) {
+ if (cmd[0].equals("leftMemory")) {
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
- List< ? > expectedLeftTuples = (List< ? >) MVEL.eval( listString,
- vars );
+ vars.put("h", handles);
+ List<?> expectedLeftTuples = (List<?>) MVEL.eval(
+ listString, vars);
LeftTupleMemory leftMemory = memory.getLeftTupleMemory();
- if ( expectedLeftTuples.isEmpty() && leftMemory.size() != 0 ) {
- throw new AssertionError( "line " + step.getLine() + ": left Memory expected [] actually " + leftMemory );
- } else if ( expectedLeftTuples.isEmpty() && leftMemory.size() == 0 ) {
+ if (expectedLeftTuples.isEmpty() && leftMemory.size() != 0) {
+ throw new AssertionFailedError("line " + step.getLine()
+ + ": left Memory expected [] actually "
+ + print(leftMemory, lrUnlinkingEnabled));
+ } else if (expectedLeftTuples.isEmpty()
+ && leftMemory.size() == 0) {
return;
}
- // we always lookup from the first element, in case it's indexed
- List<InternalFactHandle> first = (List<InternalFactHandle>) expectedLeftTuples.get( 0 );
- LeftTuple firstTuple = new LeftTuple( first.get( 0 ),
- null,
- false );
- for ( int i = 1; i < first.size(); i++ ) {
- firstTuple = new LeftTuple( firstTuple,
- null,
- false );
+ // we always lookup from the first element, in case it's
+ // indexed
+ List<InternalFactHandle> first = (List<InternalFactHandle>) expectedLeftTuples
+ .get(0);
+ LeftTuple firstTuple = new LeftTuple(first.get(0), null,
+ false);
+ for (int i = 1; i < first.size(); i++) {
+ firstTuple = new LeftTuple(firstTuple, null, false);
}
List<LeftTuple> leftTuples = new ArrayList<LeftTuple>();
- for ( LeftTuple leftTuple = memory.getLeftTupleMemory().getFirst( firstTuple ); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getNext() ) {
- leftTuples.add( leftTuple );
+ for (LeftTuple leftTuple = memory.getLeftTupleMemory()
+ .getFirst(firstTuple); leftTuple != null; leftTuple = (LeftTuple) leftTuple
+ .getNext()) {
+ leftTuples.add(leftTuple);
}
- List<List<InternalFactHandle>> actualLeftTuples = new ArrayList<List<InternalFactHandle>>( leftTuples.size() );
- for ( LeftTuple leftTuple : leftTuples ) {
- List<InternalFactHandle> tupleHandles = Arrays.asList( leftTuple.toFactHandles() );
- actualLeftTuples.add( tupleHandles );
+
+
+ if (lrUnlinkingEnabled) {
+ // When L&R Unlinking is active, we need to sort the tuples here,
+ // because we might have asserted things in the wrong order,
+ // because linking a node's side means populating its memory
+ // from the OTN which stores things in a hash-set, so insertion order is not kept.
+ Collections.sort(leftTuples, new LeftTupleComparator());
}
+
+ List<List<InternalFactHandle>> actualLeftTuples = getHandlesList(leftTuples);
+
- if ( !expectedLeftTuples.equals( actualLeftTuples ) ) {
- throw new AssertionError( "line " + step.getLine() + ": left Memory expected " + expectedLeftTuples + " actually " + actualLeftTuples );
+ if (!expectedLeftTuples.equals(actualLeftTuples)) {
+ throw new AssertionFailedError("line " + step.getLine()
+ + ": left Memory expected "
+ + print(expectedLeftTuples) + " actually "
+ + print(actualLeftTuples));
}
- } else if ( cmd[0].equals( "rightMemory" ) ) {
+ } else if (cmd[0].equals("rightMemory")) {
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
- List< ? > expectedFactHandles = (List< ? >) MVEL.eval( listString,
- vars );
+ vars.put("h", handles);
+ List<?> expectedFactHandles = (List<?>) MVEL.eval(
+ listString, vars);
RightTupleMemory rightMemory = memory.getRightTupleMemory();
- if ( expectedFactHandles.isEmpty() && rightMemory.size() != 0 ) {
- throw new AssertionError( "line " + step.getLine() + ": right Memory expected [] actually " + rightMemory );
- } else if ( expectedFactHandles.isEmpty() && rightMemory.size() == 0 ) {
+ if (expectedFactHandles.isEmpty()
+ && rightMemory.size() != 0) {
+ throw new AssertionFailedError("line " + step.getLine()
+ + ": right Memory expected [] actually "
+ + print(rightMemory));
+ } else if (expectedFactHandles.isEmpty()
+ && rightMemory.size() == 0) {
return;
}
- RightTuple first = new RightTuple( (InternalFactHandle) expectedFactHandles.get( 0 ) );
+ RightTuple first = new RightTuple(
+ (InternalFactHandle) expectedFactHandles.get(0));
List<RightTuple> actualRightTuples = new ArrayList<RightTuple>();
- for ( RightTuple rightTuple = memory.getRightTupleMemory().getFirst( first ); rightTuple != null; rightTuple = (RightTuple) rightTuple.getNext() ) {
- actualRightTuples.add( rightTuple );
+ for (RightTuple rightTuple = memory.getRightTupleMemory()
+ .getFirst(first); rightTuple != null; rightTuple = (RightTuple) rightTuple
+ .getNext()) {
+ actualRightTuples.add(rightTuple);
}
- if ( expectedFactHandles.size() != actualRightTuples.size() ) {
- throw new AssertionError( "line " + step.getLine() + ": right Memory expected " + expectedFactHandles + " actually " + actualRightTuples );
+ if (expectedFactHandles.size() != actualRightTuples.size()) {
+ throw new AssertionFailedError("line " + step.getLine()
+ + ": right Memory expected "
+ + print(expectedFactHandles) + " actually "
+ + print(actualRightTuples));
}
- for ( int i = 0, length = actualRightTuples.size(); i < length; i++ ) {
- if ( expectedFactHandles.get( i ) != actualRightTuples.get( i ).getFactHandle() ) {
- throw new AssertionError( "line " + step.getLine() + ": right Memory expected " + expectedFactHandles + " actually " + actualRightTuples );
+ for (int i = 0, length = actualRightTuples.size(); i < length; i++) {
+ if (expectedFactHandles.get(i) != actualRightTuples
+ .get(i).getFactHandle()) {
+ throw new AssertionFailedError("line "
+ + step.getLine()
+ + ": right Memory expected ["
+ + print(expectedFactHandles) + "] actually ["
+ + print(actualRightTuples)
+ + "]");
}
}
} else {
- throw new IllegalArgumentException( "line " + step.getLine() + ": command does not exist " + Arrays.toString( cmd ) );
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": command does not exist "
+ + Arrays.toString(cmd));
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
- private void riaNode(DslStep step,
- RightInputAdapterNode node,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private List<List<InternalFactHandle>> getHandlesList(
+ List<LeftTuple> leftTuples) {
+ List<List<InternalFactHandle>> actualLeftTuples = new ArrayList<List<InternalFactHandle>>(
+ leftTuples.size());
+ for (LeftTuple leftTuple : leftTuples) {
+ List<InternalFactHandle> tupleHandles = Arrays
+ .asList(leftTuple.toFactHandles());
+ actualLeftTuples.add(tupleHandles);
+ }
+ return actualLeftTuples;
+ }
+
+ private String print(LeftTupleMemory leftMemory, boolean lrUnlinkingEnabled) {
+
+ List<LeftTuple> tuples = new ArrayList<LeftTuple>();
+ Iterator it = leftMemory.iterator();
+ for ( LeftTuple tuple = (LeftTuple) it.next(); tuple != null; tuple = (LeftTuple) it.next() ) {
+ tuples.add(tuple);
+ }
+
+ if (lrUnlinkingEnabled) {
+ // Necessary only when L&R unlinking are active.
+ Collections.sort(tuples, new LeftTupleComparator());
+ }
+
+ return print(getHandlesList(tuples));
+ }
+
+ private String print(RightTupleMemory memory) {
+
+ List<RightTuple> tuples = new ArrayList<RightTuple>();
+ Iterator it = memory.iterator();
+
+ for ( RightTuple tuple = (RightTuple) it.next(); tuple != null; tuple = (RightTuple) it.next() ) {
+ tuples.add(tuple);
+ }
+
+ return "[" + print(tuples) + "]";
+ }
+
+ /** Provides better error messages. */
+ protected String print(List<?> tuples) {
+
+ StringBuilder b = new StringBuilder();
+
+ for (java.util.Iterator iterator = tuples.iterator(); iterator.hasNext();) {
+
+ Object tuple = (Object) iterator.next();
+
+ if (tuple instanceof List<?>) {
+ b.append("[");
+ b.append(print((List<?>) tuple));
+ b.append("]");
+ } else if (tuple instanceof InternalFactHandle){
+ InternalFactHandle h = (InternalFactHandle) tuple;
+ b.append("h").append(h.getId()-1);
+ } else if (tuple instanceof RightTuple){
+ InternalFactHandle h = (InternalFactHandle) ((RightTuple) tuple).getFactHandle();
+ b.append("h").append(h.getId()-1);
+ }
+
+ if(iterator.hasNext())
+ b.append(", ");
+ }
+
+ if (b.length() == 0)
+ return "[]";
+
+ return b.toString();
+ }
+
+
+ private void riaNode(DslStep step, RightInputAdapterNode node,
+ Map<String, Object> context, InternalWorkingMemory wm) {
try {
List<String[]> cmds = step.getCommands();
- List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
+ List<InternalFactHandle> handles = (List<InternalFactHandle>) context
+ .get("Handles");
- final ObjectHashMap memory = (ObjectHashMap) wm.getNodeMemory( node );
- for ( String[] cmd : cmds ) {
- if ( cmd[0].equals( "leftMemory" ) ) {
+ final ObjectHashMap memory = (ObjectHashMap) wm.getNodeMemory(node);
+ for (String[] cmd : cmds) {
+ if (cmd[0].equals("leftMemory")) {
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
- List< ? > expectedLeftTuples = (List< ? >) MVEL.eval( listString,
- vars );
+ vars.put("h", handles);
+ List<?> expectedLeftTuples = (List<?>) MVEL.eval(
+ listString, vars);
- if ( expectedLeftTuples.isEmpty() && memory.size() != 0 ) {
- throw new AssertionError( "line " + step.getLine() + ": left Memory expected [] actually " + memory );
- } else if ( expectedLeftTuples.isEmpty() && memory.size() == 0 ) {
+ if (expectedLeftTuples.isEmpty() && memory.size() != 0) {
+ throw new AssertionFailedError("line " + step.getLine()
+ + ": left Memory expected [] actually "
+ + memory);
+ } else if (expectedLeftTuples.isEmpty()
+ && memory.size() == 0) {
return;
}
// create expected tuples
List<LeftTuple> leftTuples = new ArrayList<LeftTuple>();
- for ( List<InternalFactHandle> tlist : (List<List<InternalFactHandle>>) expectedLeftTuples ) {
- LeftTuple tuple = new LeftTuple( tlist.get( 0 ),
- null,
- false );
- for ( int i = 1; i < tlist.size(); i++ ) {
- tuple = new LeftTuple( tuple,
- new RightTuple( tlist.get( i ) ),
- null,
- false );
+ for (List<InternalFactHandle> tlist : (List<List<InternalFactHandle>>) expectedLeftTuples) {
+ LeftTuple tuple = new LeftTuple(tlist.get(0), null,
+ false);
+ for (int i = 1; i < tlist.size(); i++) {
+ tuple = new LeftTuple(tuple, new RightTuple(tlist
+ .get(i)), null, false);
}
- leftTuples.add( tuple );
+ leftTuples.add(tuple);
}
// get actual tuples
final List<LeftTuple> actualTuples = new ArrayList<LeftTuple>();
final Iterator it = memory.iterator();
- for ( ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next() ) {
- actualTuples.add( (LeftTuple) entry.getKey() );
+ for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it
+ .next()) {
+ actualTuples.add((LeftTuple) entry.getKey());
}
- // iterate over expected tuples and compare with actual tuples
- for ( LeftTuple tuple : leftTuples ) {
- if ( !actualTuples.remove( tuple ) ) {
- throw new AssertionError( "line " + step.getLine() + ": left Memory expected " + tuple + " not found in memory." );
+ // iterate over expected tuples and compare with actual
+ // tuples
+ for (LeftTuple tuple : leftTuples) {
+ if (!actualTuples.remove(tuple)) {
+ throw new AssertionFailedError("line "
+ + step.getLine()
+ + ": left Memory expected " + tuple
+ + " not found in memory.");
}
}
- if ( !actualTuples.isEmpty() ) {
- throw new AssertionError( "line " + step.getLine() + ": left Memory unexpected tuples in the node memory " + actualTuples );
+ if (!actualTuples.isEmpty()) {
+ throw new AssertionFailedError(
+ "line "
+ + step.getLine()
+ + ": left Memory unexpected tuples in the node memory "
+ + actualTuples);
}
} else {
- throw new IllegalArgumentException( "line " + step.getLine() + ": command does not exist " + Arrays.toString( cmd ) );
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": command does not exist "
+ + Arrays.toString(cmd));
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
- private void ruleTerminalNode(DslStep step,
- RuleTerminalNode node,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private void ruleTerminalNode(DslStep step, RuleTerminalNode node,
+ Map<String, Object> context, InternalWorkingMemory wm) {
try {
List<String[]> cmds = step.getCommands();
- //List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
+ // List<InternalFactHandle> handles = (List<InternalFactHandle>)
+ // context.get( "Handles" );
- for ( String[] cmd : cmds ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": command does not exist " + Arrays.toString( cmd ) );
+ for (String[] cmd : cmds) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": command does not exist " + Arrays.toString(cmd));
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
@SuppressWarnings("unchecked")
- private void assertObject(DslStep step,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private void assertObject(DslStep step, Map<String, Object> context,
+ InternalWorkingMemory wm) {
try {
List<String[]> cmds = step.getCommands();
- List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
- for ( String[] cmd : cmds ) {
+ List<InternalFactHandle> handles = (List<InternalFactHandle>) context
+ .get("Handles");
+ for (String[] cmd : cmds) {
try {
String nodeName = cmd[0];
- Sink sink = (Sink) context.get( nodeName );
- if ( sink == null ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": node " + nodeName + " does not exist" );
+ Sink sink = (Sink) context.get(nodeName);
+ if (sink == null) {
+ throw new IllegalArgumentException("line "
+ + step.getLine() + ": node " + nodeName
+ + " does not exist");
}
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
+ vars.put("h", handles);
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
- List< ? > list = (List< ? >) MVEL.eval( listString,
- vars );
- if ( list == null ) {
- throw new IllegalArgumentException( cmd + " does not specify an existing fact handle" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
+ List<?> list = (List<?>) MVEL.eval(listString, vars);
+ if (list == null) {
+ throw new IllegalArgumentException(cmd
+ + " does not specify an existing fact handle");
}
- for ( Object element : list ) {
- if ( element == null ) {
- throw new IllegalArgumentException( cmd + " does not specify an existing fact handle" );
+ for (Object element : list) {
+ if (element == null) {
+ throw new IllegalArgumentException(
+ cmd
+ + " does not specify an existing fact handle");
}
- if ( element instanceof InternalFactHandle ) {
+ if (element instanceof InternalFactHandle) {
InternalFactHandle handle = (InternalFactHandle) element;
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.ASSERTION,
- null,
- null,
- handle );
- ((ObjectSink) sink).assertObject( handle,
- pContext,
- wm );
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.ASSERTION, null, null,
+ handle);
+ ((ObjectSink) sink).assertObject(handle, pContext,
+ wm);
} else {
List<InternalFactHandle> tlist = (List<InternalFactHandle>) element;
- LeftTuple tuple = createTuple( context,
- tlist );
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.ASSERTION,
- null,
- tuple,
- null );
- ((LeftTupleSink) sink).assertLeftTuple( tuple,
- pContext,
- wm );
+ LeftTuple tuple = createTuple(context, tlist);
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.ASSERTION, null, tuple,
+ null);
+ ((LeftTupleSink) sink).assertLeftTuple(tuple,
+ pContext, wm);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute command " + cmd,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute command " + cmd, e);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
private LeftTuple createTuple(Map<String, Object> context,
- List<InternalFactHandle> tlist) {
+ List<InternalFactHandle> tlist) {
LeftTuple tuple = null;
- String id = getTupleId( tlist );
- for ( InternalFactHandle handle : tlist ) {
- if ( tuple == null ) {
- tuple = new LeftTuple( handle,
- null,
- false ); // do not keep generated tuples on the handle list
+ String id = getTupleId(tlist);
+ for (InternalFactHandle handle : tlist) {
+ if (tuple == null) {
+ tuple = new LeftTuple(handle, null, false); // do not keep
+ // generated tuples
+ // on the handle
+ // list
} else {
- tuple = new LeftTuple( tuple,
- new RightTuple( handle ),
- null,
- true );
+ tuple = new LeftTuple(tuple, new RightTuple(handle), null, true);
}
}
- context.put( id,
- tuple );
+ context.put(id, tuple);
return tuple;
}
private String getTupleId(List<InternalFactHandle> tlist) {
StringBuilder id = new StringBuilder();
- id.append( "T." );
- for ( InternalFactHandle handle : tlist ) {
- id.append( handle.getId() );
- id.append( "." );
+ id.append("T.");
+ for (InternalFactHandle handle : tlist) {
+ id.append(handle.getId());
+ id.append(".");
}
return id.toString();
}
- private void retractObject(DslStep step,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private void retractObject(DslStep step, Map<String, Object> context,
+ InternalWorkingMemory wm) {
try {
List<String[]> cmds = step.getCommands();
- List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
- for ( String[] cmd : cmds ) {
+ List<InternalFactHandle> handles = (List<InternalFactHandle>) context
+ .get("Handles");
+ for (String[] cmd : cmds) {
try {
String nodeName = cmd[0];
- Sink sink = (Sink) context.get( nodeName );
- if ( sink == null ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": node " + nodeName + " does not exist" );
+ Sink sink = (Sink) context.get(nodeName);
+ if (sink == null) {
+ throw new IllegalArgumentException("line "
+ + step.getLine() + ": node " + nodeName
+ + " does not exist");
}
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
- List< ? > list = (List< ? >) MVEL.eval( listString,
- vars );
- if ( list == null ) {
- throw new IllegalArgumentException( Arrays.toString( cmd ) + " does not specify an existing fact handle" );
+ vars.put("h", handles);
+ List<?> list = (List<?>) MVEL.eval(listString, vars);
+ if (list == null) {
+ throw new IllegalArgumentException(Arrays.toString(cmd)
+ + " does not specify an existing fact handle");
}
- for ( Object element : list ) {
- if ( element == null ) {
- throw new IllegalArgumentException( Arrays.toString( cmd ) + " does not specify an existing fact handle" );
+ for (Object element : list) {
+ if (element == null) {
+ throw new IllegalArgumentException(
+ Arrays.toString(cmd)
+ + " does not specify an existing fact handle");
}
- if ( element instanceof InternalFactHandle ) {
+ if (element instanceof InternalFactHandle) {
InternalFactHandle handle = (InternalFactHandle) element;
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.RETRACTION,
- null,
- null,
- handle );
- if ( sink instanceof ObjectTypeNode ) {
- ((ObjectTypeNode) sink).retractObject( handle,
- pContext,
- wm );
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.RETRACTION, null, null,
+ handle);
+ if (sink instanceof ObjectTypeNode) {
+ ((ObjectTypeNode) sink).retractObject(handle,
+ pContext, wm);
} else {
- for ( RightTuple rightTuple = handle.getFirstRightTuple(); rightTuple != null; rightTuple = (RightTuple) rightTuple.getHandleNext() ) {
- rightTuple.getRightTupleSink().retractRightTuple( rightTuple,
- pContext,
- wm );
+ for (RightTuple rightTuple = handle
+ .getFirstRightTuple(); rightTuple != null; rightTuple = (RightTuple) rightTuple
+ .getHandleNext()) {
+ rightTuple.getRightTupleSink()
+ .retractRightTuple(rightTuple,
+ pContext, wm);
}
- handle.setFirstRightTuple( null );
- handle.setLastRightTuple( null );
- for ( LeftTuple leftTuple = handle.getFirstLeftTuple(); leftTuple != null; leftTuple = (LeftTuple) leftTuple.getLeftParentNext() ) {
- leftTuple.getLeftTupleSink().retractLeftTuple( leftTuple,
- pContext,
- wm );
+ handle.setFirstRightTuple(null);
+ handle.setLastRightTuple(null);
+ for (LeftTuple leftTuple = handle
+ .getFirstLeftTuple(); leftTuple != null; leftTuple = (LeftTuple) leftTuple
+ .getLeftParentNext()) {
+ leftTuple.getLeftTupleSink()
+ .retractLeftTuple(leftTuple,
+ pContext, wm);
}
- handle.setFirstLeftTuple( null );
- handle.setLastLeftTuple( null );
+ handle.setFirstLeftTuple(null);
+ handle.setLastLeftTuple(null);
}
} else {
List<InternalFactHandle> tlist = (List<InternalFactHandle>) element;
- String id = getTupleId( tlist );
- LeftTuple tuple = (LeftTuple) context.remove( id );
- if ( tuple == null ) {
- throw new IllegalArgumentException( "Tuple not found: " + id + " : " + tlist.toString() );
+ String id = getTupleId(tlist);
+ LeftTuple tuple = (LeftTuple) context.remove(id);
+ if (tuple == null) {
+ throw new IllegalArgumentException(
+ "Tuple not found: " + id + " : "
+ + tlist.toString());
}
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.RETRACTION,
- null,
- tuple,
- null );
- ((LeftTupleSink) sink).retractLeftTuple( tuple,
- pContext,
- wm );
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.RETRACTION, null, tuple,
+ null);
+ ((LeftTupleSink) sink).retractLeftTuple(tuple,
+ pContext, wm);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute command " + Arrays.toString( cmd ),
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute command "
+ + Arrays.toString(cmd), e);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
- private void modifyObject(DslStep step,
- Map<String, Object> context,
- InternalWorkingMemory wm) {
+ private void modifyObject(DslStep step, Map<String, Object> context,
+ InternalWorkingMemory wm) {
try {
List<String[]> cmds = step.getCommands();
- List<InternalFactHandle> handles = (List<InternalFactHandle>) context.get( "Handles" );
- for ( String[] cmd : cmds ) {
+ List<InternalFactHandle> handles = (List<InternalFactHandle>) context
+ .get("Handles");
+ for (String[] cmd : cmds) {
try {
String nodeName = cmd[0];
- Sink sink = (Sink) context.get( nodeName );
- if ( sink == null ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": node " + nodeName + " does not exist" );
+ Sink sink = (Sink) context.get(nodeName);
+ if (sink == null) {
+ throw new IllegalArgumentException("line "
+ + step.getLine() + ": node " + nodeName
+ + " does not exist");
}
String args = cmd[1];
- String listString = args.replaceAll( "h(\\d+)",
- "h[$1]" );
+ String listString = args.replaceAll("h(\\d+)", "h[$1]");
Map<String, Object> vars = new HashMap<String, Object>();
- vars.put( "h",
- handles );
- List< ? > list = (List< ? >) MVEL.eval( listString,
- vars );
- if ( list == null ) {
- throw new IllegalArgumentException( Arrays.toString( cmd ) + " does not specify an existing fact handle" );
+ vars.put("h", handles);
+ List<?> list = (List<?>) MVEL.eval(listString, vars);
+ if (list == null) {
+ throw new IllegalArgumentException(Arrays.toString(cmd)
+ + " does not specify an existing fact handle");
}
- for ( Object element : list ) {
- if ( element == null ) {
- throw new IllegalArgumentException( Arrays.toString( cmd ) + " does not specify an existing fact handle" );
+ for (Object element : list) {
+ if (element == null) {
+ throw new IllegalArgumentException(
+ Arrays.toString(cmd)
+ + " does not specify an existing fact handle");
}
- if ( element instanceof InternalFactHandle ) {
+ if (element instanceof InternalFactHandle) {
InternalFactHandle handle = (InternalFactHandle) element;
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.MODIFICATION,
- null,
- null,
- handle );
- ModifyPreviousTuples modifyPreviousTuples = new ModifyPreviousTuples( handle.getFirstLeftTuple(),
- handle.getFirstRightTuple() );
- handle.setFirstLeftTuple( null );
- handle.setFirstRightTuple( null );
- handle.setLastLeftTuple( null );
- handle.setLastRightTuple( null );
- ((ObjectSink) sink).modifyObject( handle,
- modifyPreviousTuples,
- pContext,
- wm );
- modifyPreviousTuples.retractTuples( pContext,
- wm );
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.MODIFICATION, null,
+ null, handle);
+ ModifyPreviousTuples modifyPreviousTuples = new ModifyPreviousTuples(
+ handle.getFirstLeftTuple(), handle
+ .getFirstRightTuple());
+ handle.setFirstLeftTuple(null);
+ handle.setFirstRightTuple(null);
+ handle.setLastLeftTuple(null);
+ handle.setLastRightTuple(null);
+ ((ObjectSink) sink).modifyObject(handle,
+ modifyPreviousTuples, pContext, wm);
+ modifyPreviousTuples.retractTuples(pContext, wm);
} else {
List<InternalFactHandle> tlist = (List<InternalFactHandle>) element;
- String id = getTupleId( tlist );
- LeftTuple tuple = (LeftTuple) context.get( id );
- if ( tuple == null ) {
- throw new IllegalArgumentException( "Tuple not found: " + id + " : " + tlist.toString() );
+ String id = getTupleId(tlist);
+ LeftTuple tuple = (LeftTuple) context.get(id);
+ if (tuple == null) {
+ throw new IllegalArgumentException(
+ "Tuple not found: " + id + " : "
+ + tlist.toString());
}
- PropagationContext pContext = new PropagationContextImpl( wm.getNextPropagationIdCounter(),
- PropagationContext.MODIFICATION,
- null,
- tuple,
- null );
- ((LeftTupleSink) sink).modifyLeftTuple( tuple,
- pContext,
- wm );
+ PropagationContext pContext = new PropagationContextImpl(
+ wm.getNextPropagationIdCounter(),
+ PropagationContext.MODIFICATION, null,
+ tuple, null);
+ ((LeftTupleSink) sink).modifyLeftTuple(tuple,
+ pContext, wm);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute command " + cmd,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute command " + cmd, e);
}
}
- } catch ( Exception e ) {
- throw new IllegalArgumentException( "line " + step.getLine() + ": unable to execute step " + step,
- e );
+ } catch (Exception e) {
+ throw new IllegalArgumentException("line " + step.getLine()
+ + ": unable to execute step " + step, e);
}
}
public static NodeTestCase compile(final Reader reader) throws IOException {
- NodeTestDSLParser parser = getParser( reader );
- return compile( parser );
+ NodeTestDSLParser parser = getParser(reader);
+ return compile(parser);
}
public static NodeTestCase compile(final InputStream is) throws IOException {
- NodeTestDSLParser parser = getParser( is );
- return compile( parser );
+ NodeTestDSLParser parser = getParser(is);
+ return compile(parser);
}
public static NodeTestCase compile(final String source) throws IOException {
- NodeTestDSLParser parser = getParser( source );
- return compile( parser );
+ NodeTestDSLParser parser = getParser(source);
+ return compile(parser);
}
private static NodeTestCase compile(final NodeTestDSLParser parser) {
try {
compilation_unit_return cur = parser.compilation_unit();
- if ( parser.hasErrors() ) {
+ if (parser.hasErrors()) {
NodeTestCase result = new NodeTestCase();
- result.setErrors( parser.getErrorMessages() );
+ result.setErrors(parser.getErrorMessages());
return result;
}
- NodeTestCase testCase = walk( parser.getTokenStream(),
- (CommonTree) cur.getTree() );
+ NodeTestCase testCase = walk(parser.getTokenStream(),
+ (CommonTree) cur.getTree());
return testCase;
- } catch ( RecognitionException e ) {
+ } catch (RecognitionException e) {
NodeTestCase result = new NodeTestCase();
- result.setErrors( Collections.singletonList( e.getMessage() ) );
+ result.setErrors(Collections.singletonList(e.getMessage()));
return result;
}
}
- private static NodeTestCase walk(TokenStream tokenStream,
- Tree resultTree) throws RecognitionException {
- CommonTreeNodeStream nodes = new CommonTreeNodeStream( resultTree );
+ private static NodeTestCase walk(TokenStream tokenStream, Tree resultTree)
+ throws RecognitionException {
+ CommonTreeNodeStream nodes = new CommonTreeNodeStream(resultTree);
// AST nodes have payload that point into token stream
- nodes.setTokenStream( tokenStream );
+ nodes.setTokenStream(tokenStream);
// Create a tree walker attached to the nodes stream
- NodeTestDSLTree walker = new NodeTestDSLTree( nodes );
+ NodeTestDSLTree walker = new NodeTestDSLTree(nodes);
walker.compilation_unit();
return walker.getTestCase();
}
- private static NodeTestDSLParser getParser(final Reader reader) throws IOException {
- NodeTestDSLLexer lexer = new NodeTestDSLLexer( new ANTLRReaderStream( reader ) );
- NodeTestDSLParser parser = new NodeTestDSLParser( new CommonTokenStream( lexer ) );
+ private static NodeTestDSLParser getParser(final Reader reader)
+ throws IOException {
+ NodeTestDSLLexer lexer = new NodeTestDSLLexer(new ANTLRReaderStream(
+ reader));
+ NodeTestDSLParser parser = new NodeTestDSLParser(new CommonTokenStream(
+ lexer));
return parser;
}
- private static NodeTestDSLParser getParser(final InputStream is) throws IOException {
- NodeTestDSLLexer lexer = new NodeTestDSLLexer( new ANTLRInputStream( is ) );
- NodeTestDSLParser parser = new NodeTestDSLParser( new CommonTokenStream( lexer ) );
+ private static NodeTestDSLParser getParser(final InputStream is)
+ throws IOException {
+ NodeTestDSLLexer lexer = new NodeTestDSLLexer(new ANTLRInputStream(is));
+ NodeTestDSLParser parser = new NodeTestDSLParser(new CommonTokenStream(
+ lexer));
return parser;
}
- private static NodeTestDSLParser getParser(final String source) throws IOException {
- NodeTestDSLLexer lexer = new NodeTestDSLLexer( new ANTLRStringStream( source ) );
- NodeTestDSLParser parser = new NodeTestDSLParser( new CommonTokenStream( lexer ) );
+ private static NodeTestDSLParser getParser(final String source)
+ throws IOException {
+ NodeTestDSLLexer lexer = new NodeTestDSLLexer(new ANTLRStringStream(
+ source));
+ NodeTestDSLParser parser = new NodeTestDSLParser(new CommonTokenStream(
+ lexer));
return parser;
}
+ private final class LeftTupleComparator implements Comparator<LeftTuple> {
+ public int compare(LeftTuple o1, LeftTuple o2) {
+
+ InternalFactHandle[] h1 = o1.getFactHandles();
+ InternalFactHandle[] h2 = o2.getFactHandles();
+
+ // Handles have to be compared in the inverse order.
+ for (int i = (h1.length-1); i >= 0; i--) {
+
+ int diff = h1[i].getId() - h2[i].getId();
+
+ // Will continue comparing handles until
+ // a difference is found.
+ if (diff != 0)
+ return diff;
+ }
+
+ return 0;
+ }
+ }
+
public static class EmptyNotifier extends RunNotifier {
public static final EmptyNotifier INSTANCE = new EmptyNotifier();
@@ -839,7 +974,8 @@
}
@Override
- public void fireTestStarted(Description description) throws StoppedByUserException {
+ public void fireTestStarted(Description description)
+ throws StoppedByUserException {
}
}
}
\ No newline at end of file
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngineTest.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngineTest.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/ReteDslTestEngineTest.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -21,20 +21,17 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import junit.framework.TestCase;
import org.drools.FactHandle;
import org.drools.Person;
-import org.drools.RuleBaseConfiguration;
import org.drools.RuleBaseFactory;
import org.drools.WorkingMemory;
import org.drools.base.ClassObjectType;
import org.drools.common.DefaultFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
-import org.drools.common.NodeMemory;
import org.drools.common.PropagationContextImpl;
import org.drools.reteoo.BetaMemory;
import org.drools.reteoo.JoinNode;
@@ -43,11 +40,11 @@
import org.drools.reteoo.ObjectTypeNode;
import org.drools.reteoo.ReteooRuleBase;
import org.drools.reteoo.ReteooWorkingMemory;
-import org.drools.reteoo.RuleTerminalNode;
+import org.drools.reteoo.builder.BuildContext;
import org.drools.reteoo.test.dsl.DslStep;
-import org.drools.reteoo.test.dsl.NodeTestDef;
import org.drools.reteoo.test.dsl.NodeTestCase;
import org.drools.reteoo.test.dsl.NodeTestCaseResult;
+import org.drools.reteoo.test.dsl.NodeTestDef;
import org.drools.reteoo.test.dsl.NodeTestCaseResult.NodeTestResult;
import org.drools.reteoo.test.dsl.NodeTestCaseResult.Result;
import org.drools.rule.Declaration;
@@ -741,6 +738,21 @@
memory.getLeftTupleMemory().size() );
}
+ public void testConfigOptions() throws IOException {
+ String str = "TestCase 'testOTN'\nTest 'dummy'\n";
+ str += "Config:\n";
+ str += " lrUnlinkingEnabled, true;\n";
+ str += "ObjectTypeNode:\n";
+ str += " otn1, java.lang.Integer;\n";
+
+ NodeTestResult result = executeTest( str );
+ Map<String, Object> map = result.context;
+
+ BuildContext buildCtx = (BuildContext) map.get( ReteDslTestEngine.BUILD_CONTEXT );
+ assertTrue(buildCtx.getRuleBase().getConfiguration().isLRUnlinkingEnabled());
+ }
+
+
public void testNotNodeStep() throws IOException {
String str = "TestCase 'testOTN'\nTest 'dummy'\n";
str += "ObjectTypeNode:\n";
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/SingleTestCase.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/SingleTestCase.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/SingleTestCase.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -62,6 +62,7 @@
}
for( NodeTestDef test : tcase.getTests() ) {
if( test.getName().equals( testName ) ) {
+ result.setFileName(file.getName());
result.setName( tcase.getName() );
result.setImports( tcase.getImports() );
result.setSetup( tcase.getSetup() );
Added: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/ConfigStep.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/ConfigStep.java (rev 0)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/ConfigStep.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -0,0 +1,44 @@
+package org.drools.reteoo.test.dsl;
+
+import static org.drools.reteoo.test.ReteDslTestEngine.BUILD_CONTEXT;
+import static org.drools.reteoo.test.ReteDslTestEngine.WORKING_MEMORY;
+
+import java.util.List;
+import java.util.Map;
+
+import org.drools.RuleBaseConfiguration;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.reteoo.ReteooRuleBase;
+import org.drools.reteoo.builder.BuildContext;
+
+/**
+ * A step in the setup of a nodeTestCase, it allows configuration parameters to
+ * be passed.
+ *
+ * @author lgomes
+ *
+ */
+public class ConfigStep implements Step {
+
+ public void execute(Map<String, Object> context, List<String[]> args) {
+
+ RuleBaseConfiguration conf = new RuleBaseConfiguration();
+
+ for (String[] configOption : args) {
+ conf.setProperty("drools." + configOption[0], configOption[1]);
+ }
+
+ ReteooRuleBase rbase = new ReteooRuleBase("ID", conf);
+ BuildContext buildContext = new BuildContext(rbase, rbase
+ .getReteooBuilder().getIdGenerator());
+
+ InternalWorkingMemory wm = (InternalWorkingMemory) rbase
+ .newStatefulSession(true);
+
+ // Overwrite values now taking into account the configuration options.
+ context.put(BUILD_CONTEXT, buildContext);
+ context.put(WORKING_MEMORY, wm);
+
+ }
+
+}
Modified: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/NodeTestCase.java
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/NodeTestCase.java 2010-11-19 16:38:06 UTC (rev 36013)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/java/org/drools/reteoo/test/dsl/NodeTestCase.java 2010-11-21 23:40:59 UTC (rev 36014)
@@ -21,14 +21,15 @@
import org.junit.runner.Description;
-
/**
* A class to describe a test case for reteoo nodes
*
* @author etirelli
*/
public class NodeTestCase {
-
+
+ public static final String SUFFIX = ".nodeTestCase";
+
private String name;
private List<String> imports;
private List<DslStep> setup;
@@ -36,48 +37,58 @@
private List<NodeTestDef> tests;
private List<String> errors;
private Description description;
-
+ private String fileName;
+
public NodeTestCase() {
this("");
}
-
- public NodeTestCase( String name ) {
+
+ public NodeTestCase(String name) {
this.name = name;
this.imports = new ArrayList<String>();
this.setup = new ArrayList<DslStep>();
this.tearDown = new ArrayList<DslStep>();
this.tests = new ArrayList<NodeTestDef>();
}
-
+
public String getName() {
return name;
}
+
public void setName(String name) {
this.name = name;
}
- public void addImport( String clazz ) {
- this.imports.add( clazz );
+
+ public void addImport(String clazz) {
+ this.imports.add(clazz);
}
+
public List<String> getImports() {
return this.imports;
}
+
public List<DslStep> getSetup() {
return setup;
}
+
public void addSetupStep(DslStep step) {
- this.setup.add( step );
+ this.setup.add(step);
}
+
public List<DslStep> getTearDown() {
return tearDown;
}
+
public void addTearDownStep(DslStep step) {
- this.tearDown.add( step );
+ this.tearDown.add(step);
}
+
public List<NodeTestDef> getTests() {
return tests;
}
+
public void addTest(NodeTestDef test) {
- this.tests.add( test );
+ this.tests.add(test);
}
public List<String> getErrors() {
@@ -89,7 +100,7 @@
}
public boolean hasErrors() {
- return this.errors != null && ! this.errors.isEmpty();
+ return this.errors != null && !this.errors.isEmpty();
}
public Description getDescription() {
@@ -111,4 +122,24 @@
public void setTearDown(List<DslStep> tearDown) {
this.tearDown = tearDown;
}
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+
+ this.fileName = removeSuffix(fileName);
+ }
+
+ private String removeSuffix(String name) {
+ // removes the suffix, if present.
+ if (name.endsWith(SUFFIX)) {
+ return name.substring(0, name.indexOf(SUFFIX));
+ }
+
+ return name;
+
+ }
+
}
Added: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingComplex.nodeTestCase
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingComplex.nodeTestCase (rev 0)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingComplex.nodeTestCase 2010-11-21 23:40:59 UTC (rev 36014)
@@ -0,0 +1,57 @@
+TestCase "RightUnlinkingComplex"
+
+Setup
+ Config:
+ lrUnlinkingEnabled, true;
+ ObjectTypeNode:
+ otnLeft1, org.drools.Person;
+ LeftInputAdapterNode:
+ lian0, otnLeft1;
+ ObjectTypeNode:
+ otnRight1, org.drools.Person;
+ ObjectTypeNode:
+ otnRight2, org.drools.Person;
+ Binding:
+ p1, 0, org.drools.Person, age;
+ Binding:
+ p1, 0, org.drools.Person, likes;
+ JoinNode:
+ join1, lian0, otnRight1;
+ age, !=, p1;
+ JoinNode:
+ join2, join1, otnRight1;
+ likes, ==, p1;
+ JoinNode:
+ join3, join2, otnRight2;
+ age, !=, p1;
+ Facts:
+ new org.drools.Person('darth', 35, 'stilton'), new org.drools.Person('bobba', 36, 'brie'),
+ new org.drools.Person('yoda', 37, 'cammembert'), new org.drools.Person('luke', 38, 'minas'),
+ new org.drools.Person('dave', 33, 'prato'), new org.drools.Person('bob', 32, 'parmigiano'),
+ new org.drools.Person('dave', 31, 'stilton'), new org.drools.Person('bob', 30, 'minas');
+
+
+Test "RightUnlinkingComplex"
+
+ assert:
+ otnRight1, [h1];
+ join1:
+ leftMemory, [];
+ rightMemory, []; // right is side is unlinked - PROBLEM here!
+ assert:
+ otnLeft1, [h0];
+ join1:
+ leftMemory, [[h0]];
+ rightMemory, [h1];
+ join2:
+ leftMemory, [[h0, h1]];
+ rightMemory, [h1];
+ join3:
+ leftMemory, [];
+ rightMemory, [];
+
+ assert:
+ otnRight2, [h3];
+ join3:
+ leftMemory, [];
+ rightMemory, [];
Added: labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingModify.nodeTestCase
===================================================================
--- labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingModify.nodeTestCase (rev 0)
+++ labs/jbossrules/branches/lr_unlinking_20101116/drools-core/src/test/resources/org/drools/reteoo/test/RightUnlinkingModify.nodeTestCase 2010-11-21 23:40:59 UTC (rev 36014)
@@ -0,0 +1,70 @@
+TestCase "RightUnlinkingModify"
+
+Setup
+ Config:
+ lrUnlinkingEnabled, true;
+ ObjectTypeNode:
+ otnLeft1, org.drools.Person;
+ LeftInputAdapterNode:
+ lian0, otnLeft1;
+ ObjectTypeNode:
+ otnRight1, org.drools.Person;
+ ObjectTypeNode:
+ otnRight2, org.drools.Person;
+ ObjectTypeNode:
+ otnRight3, org.drools.Person;
+ Binding:
+ p1, 0, org.drools.Person, age;
+ JoinNode:
+ join1, lian0, otnRight1;
+ age, !=, p1;
+ JoinNode:
+ join2, join1, otnRight2;
+ age, !=, p1;
+ JoinNode:
+ join3, join1, otnRight3;
+ age, !=, p1;
+ Facts:
+ new org.drools.Person('darth', 35), new org.drools.Person('bobba', 36),
+ new org.drools.Person('yoda', 37), new org.drools.Person('luke', 38),
+ new org.drools.Person('dave', 33), new org.drools.Person('bob', 32),
+ new org.drools.Person('dave', 31), new org.drools.Person('bob', 30);
+
+
+Test "RightUnlinkingModify"
+
+ assert:
+ otnRight1, [h0];
+ otnRight2, [h1];
+ join1:
+ rightMemory, [];
+ join2:
+ rightMemory, [];
+
+ assert:
+ otnLeft1, [h2];
+ join1:
+ leftMemory, [[h2]];
+ rightMemory, [h0];
+ join2:
+ leftMemory, [[h2,h0]];
+ rightMemory, [h1];
+
+ With:
+ h2, age = 35;
+ modify:
+ otnLeft1, [h2];
+
+ // With the modify, [h2,h0] don't match anymore
+ join1:
+ leftMemory, [[h2]];
+ rightMemory, [h0];
+ join2:
+ leftMemory, []; // left tuple is retracted
+ rightMemory, [h1]; // right side is not unlinked
+
+ assert:
+ otnRight2, [h3];
+ join2:
+ rightMemory, [h1,h3];
+
More information about the jboss-svn-commits
mailing list